1

I want to get the input of CSV in plumber API and output it as CSV.

I can do both individually(with the help of the links attached below).

But I am not able to do it together.

Using Serializer from Github Link:

serializer_csv <- function(){
  function(val, req, res, errorHandler){
    tryCatch({
      res$setHeader("Content-Type", "text/plain")
      res$setHeader("Content-Disposition", 'attachment; filename="xxx.csv"')
      res$body <- paste0(val, collapse="\n")
      return(res$toResponse())
    }, error=function(e){
      errorHandler(req, res, e)
    })
  }
}
plumber::addSerializer("csv", serializer_csv)
plumber::plumber$new("plumber-csv.R")$run(port = 8833)

Plumber File:

#* @serializer csv
#* @get /csv
function() {
  df <- data.frame(CHAR = letters, NUM = rnorm(length(letters)), stringsAsFactors = F)
  csv_file <- tempfile(fileext = ".csv")
  on.exit(unlink(csv_file), add = TRUE)
  write.csv(df, file = csv_file)
  readLines(csv_file)
}

Here, instead of using readLines I directly tried to return(csv_file). It downloads a temporary file. But on my local disk that file doesn't show up.

So what could be the way to input as well output CSV file? Links:

Link 1: StackOverFlow

Link 2: GitHub

skad00sh
  • 171
  • 11

1 Answers1

3

This work in version 4.6.0 of Plumber but is a bit hacky. You could replace write.csv and read.csv with fwrite, fread from data.table or format_csv from readr.

library(plumber)
serializer_csv <- function(){
  function(val, req, res, errorHandler){
    tryCatch({
      res$setHeader("Content-Type", "text/csv")
      res$setHeader("Content-Disposition", paste0('attachment; filename="', names(val),'.csv"'))
      content <- capture.output(write.csv(val[[1]]), type = "output")
      res$body <- charToRaw(paste0(content, collapse = "\n"))
      return(res$toResponse())
    }, error=function(e){
      errorHandler(req, res, e)
    })
  }
}
plumber::addSerializer("csv", serializer_csv)
plumber::plumber$new("plumber-csv.R")$run(port = 8833)

plumber.R

#* @serializer csv
#* @post /csv
function(req) {
  req$rook.input$rewind()
  f <- tempfile()
  writeLines(req$rook.input$read_lines(), f)
  df <- read.csv(f)
  response <- list(response = df)
  response
}

Testing

library(httr)
library(readr)

write.csv(mtcars, "mtcars.csv")
req <- POST("http://127.0.0.1:8833/csv", body = upload_file("mtcars.csv"))
content(req)
Bruno Tremblay
  • 756
  • 4
  • 9