How can I retrieve data from the request body sent to a Plumber API?

83 Views Asked by At

I am currently working on a project involving a Plumber API, and I've encountered a challenge related to handling CSV files in the body of HTTP requests.

I have a Plumber API where I need to receive two CSV files in the body of a POST request sent from Postman (for example). I am unsure how to do that.

I've read about Plumber Parsers and there was a parser_csv but couldn't figure out how to use that to get that data from request body!

    #* Process two files in the request body
    #* @post /process_files
    #* @parser multipart/form-data
    function(req, res) {
     
      if (is.null(req$files) || length(req$files) < 2) {
        res$status <- 400
        res$body <- '{"error": "Two files must be included in the request."}'
        return()
      }
    
      
      file1 <- req$files$file1
      file2 <- req$files$file2

  ## process thet data here 

  res$status <- 200
  res$body <- '{"message": "Files processed successfully."}'
}

Can someone please guide me?

2

There are 2 best solutions below

2
Leon On

Handling CSV files in the body of HTTP requests using a Plumber API in R requires you to set up your endpoint to accept files via a multipart/form-data parser. This parser is ideal for handling file uploads. It looks like you're on the right track with your current setup. Here's how you can modify your function to handle two CSV files:

Endpoint Setup: Ensure your endpoint is set up to handle multipart/form-data.

File Handling: In your function, check if two files have been uploaded. If so, read them as CSV files.

CSV Reading: Use appropriate functions like read.csv or read_csv from the readr package to read the CSV files.

Here's a revised version of your function:

    function(req, res) {
    # Check if two files are present
    if (is.null(req$files) || length(req$files) < 2) {
        res$status <- 400
        res$body <- '{"error": "Two files must be included in the request."}'
        return(res)
    }

    # Read the files as CSV
    tryCatch({
        file1 <- read.csv(req$files$file1$tempfile, stringsAsFactors = FALSE)
        file2 <- read.csv(req$files$file2$tempfile, stringsAsFactors = FALSE)
        # Process the data here
        # ...

        # Successful response
        res$status <- 200
        res$body <- '{"message": "Files processed successfully."}'
    }, error = function(e) {
        # Error handling
        res$status <- 500
        res$body <- sprintf('{"error": "Failed to process files: %s"}', e$message)
    })

    return(res)
}

Make sure you test the endpoint with files using a tool like Postman. Set the request type to POST, use the multipart/form-data encoding, and attach two CSV files with the keys file1 and file2.

0
MrFlick On

Here's something that should work with the latest parsers.

#* Process two files in the request body
#* @post /process_files
#* @parser multi
function(req, res) {
  
  data <- setNames(
    lapply(req$body, function(x) read.csv(text=rawToChar(x$value))),
    sapply(req$body, function(x) x$name)
  )
  
  res$status <- 200
  res$body <- data
}

You use @parser multi to get the multipart parser and that will populate req$body with each of the different elements. Here I just assume they are all files and use lapply to read the data from the value of each of the incoming chunks.

You can also activate the csv parser as well and have plumber do the csv parsing. This should be roughly equivalent

#* Process two files in the request body
#* @post /process_files
#* @parser multi
#* @parser csv
function(req, res) {
  
  data <- setNames(
    lapply(req$body, function(x) x$parsed),
    sapply(req$body, function(x) x$name)
  )
  
  res$status <- 200
  res$body <- data
}