Plumber request body receive and read CSV, XLSX, and RDS files.

I am trying to write the R Plumber code to create an API that allows users to upload a CSV, XLSX, or RDS file. The function should read the data from the file and allow me to do some processing and return the updated file to the user.

I was thinking of something along the lines of this.

#* @param dataset:file 
#* @param a:str <param used for processing>.
#* @param b:str <param used for processing>.
#* @param c:number <param used for processing>.
#* @param d:number <param used for processing>.
#* @post reconciliation/auto_match
#* @response 200 Json serialized dataset extended with reconsoliation columns
#* @tag Reconciliation
function(dataset, a, b, c, d){
  
  # Check the file type of dataset param
  file_type <- **.....?**
  
  # Print the file type
  cat("Loading", file_type, "file...\n")
  
  # Load the file based on its type
  if (file_type == "rds") {data <- readRDS(**.....?**)} 
  
  else if (file_type == "csv") {
    # Check the delimiter
    first_line <- readLines(**.....?**, n = 1)
    if (grepl(";", first_line)) {
      data <- read.csv(**.....?**, sep = ";")
    } else if (grepl("\t", first_line)) {
      data <- read.csv(**.....?**, sep = "\t")
    } else {
      data <- read.csv(**.....?**, sep = ",")
    }
  } 
  else if (file_type == "xlsx") {
    data <- read.xlsx(**.....?**, sheetIndex = 1)
  } 
  else {
    stop("Unsupported file type, please use a RDS, CSV, or XLS file.")
  }
 
# Do some processing on dataset
...

# Return updated dataset to user
...

I tried to use code such as this to read the data from the dataset parameter.

Rook::Multipart$parse(dataset)$dataset$tempfile
mime::parse_multipart(dataset)

Unfortunately, nothing seems to work. I test with the 'Try it out' button in SwaggerUI. I receive errors such as these two.

<simpleError in readRDS(file): bad 'file' argument>
<simpleError in read.table(file = file, header = header, sep = sep, quote = quote,     dec = dec, fill = fill, comment.char = comment.char, ...): 'file' must be a character string or connection>

Thanks!

Hi @ivdongen

uses a similar approach. Would that help you?

Plumber has an input parser system based on the mime type in the request body. By default, only a handful of parsers are activated (txt, json, query, body, octet). In the solution below, I added two parsers, one for each match mime type (xls and xlsx). I also activated all parsers with the annotation #* @parser all.

If plumber cannot find a matching activated parser for a mime type, it returns a raw vector named with the filename.

library(plumber)

parser_xlsx <- function(...) {
	parser_read_file(function(tmpfile) {
		readxl::read_xlsx(tmpfile, sheet = 1)
	})
}

parser_xls <- function(...) {
	parser_read_file(function(tmpfile) {
		readxl::read_xls(tmpfile, sheet= 1)
	})
}

register_parser("xlsx", parser_xlsx, fixed = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
register_parser("xls", parser_xls, fixed = "application/vnd.ms-excel")

#* @param dataset:file
#* @param a:str <param used for processing>.
#* @param b:str <param used for processing>.
#* @param c:number <param used for processing>.
#* @param d:number <param used for processing>.
#* @parser all
#* @post reconciliation/auto_match
#* @response 200 Json serialized dataset extended with reconsoliation columns
#* @tag Reconciliation
function(dataset, a, b, c, d) {

	# Load the file based on its type
	if (is.raw(dataset)) {
		stop("Unsupported file type, please use a RDS, CSV, XLS or XLSX file.")
	}

	# Do some processing on dataset
	...

	# Return updated dataset to user
	...

}

Documentation reference:

This topic was automatically closed 42 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.