Shiny App File Upload: How to Save the Files Uploaded on a Shiny Gui to a Particular Destination

shiny app File Upload: How can we save the files uploaded on a shiny GUI to a particular destination?

Well, kind of. You can use observer to copy the file on upload:

library(shiny)

shinyApp(
ui=shinyUI(bootstrapPage(
fileInput("upload", "Upload", multiple = FALSE)
)),

server=shinyServer(function(input, output, session){
observe({
if (is.null(input$upload)) return()
file.copy(input$upload$datapath, "/some/other/path")
})
})
)

Not that I am using file.copy and not file.rename to avoid problems when the destination is located on a different device than the temporary directory.

Specify destination folder for download from an R Shiny app

You're passing reactive(file <- input$file1) as the contentType argument to downloadHandler(), which can't be good. Also, you're not writing anything to the file given as an argument to the content function.

Remove the reactive(file <- input$file1) line, and specify output_file = file in rmarkdown::render(), and your download should work.

As discussed in the comments, you won't be able to have control over the download path though -- that's something the user's web browser and their settings there will decide.

Here's a somewhat more minimal app with a functioning file download, for reference:

library(shiny)

ui <- fluidPage(
sliderInput("value", "Some value", 1, 5, 2),
downloadButton("report", "Generate report")
)

server <- function(input, output) {
output$report <- downloadHandler(
filename = "wordreport.doc",
content = function(file) {
params <- list(value = input$value)
rmarkdown::render(
system.file("examples/knitr-minimal.Rmd", package = "knitr"),
output_file = file,
params = params,
envir = new.env(parent = globalenv())
)
}
)
}

shinyApp(ui, server)

Shiny fileInput Does Not Keep File Name

Change the file.copy line to

file.copy(input$upload$datapath, paste0("your_folder/", input$upload$name))

How to specify file and path to save a file with R-shiny and shinyFiles?

Here is a working example. Again, this assumes that you run the app on your own computer, and users are allowed to access folders on this computer. You can set the root folder where user is allowed to save files (see UserFolder, user will be able to choose any subfolder of this root)

library(shiny)
library(shinyFiles)
library(xlsx)

ui <- shinyUI(fluidPage(

titlePanel("Example"),
shinySaveButton("save", "Save file", "Save file as ...", filetype=list(xlsx="xlsx"))

))

server <- shinyServer(function(input, output, session) {

observe({
volumes <- c("UserFolder"="D:/Data")
shinyFileSave(input, "save", roots=volumes, session=session)
fileinfo <- parseSavePath(volumes, input$save)
data <- data.frame(a=c(1,2))
if (nrow(fileinfo) > 0) {
write.xlsx(data, as.character(fileinfo$datapath))
}
})
})

shinyApp(ui = ui, server = server)

Passing a dataframe as a parameter from Shiny app to RMarkdown

There are several issues with your code. I'll go over them one by one

Invalid parameter in downloadHandler()

You are passing an object of class reactive to the contentType parameter of downloadHandler().

downloadHandler(
reactive(file <- input$file1), ## <--- here
filename = "report.doc",
content = function(file) {
# ...
}
)

It seems that this messes up the whole logic of downloadHandler() and leads to "server error" messages on the client side with no errors or warnings from shiny.

This line needs to be removed in order to download files successfully

Reference the Rmd-parameter correctly

When you want to access the parameter from the Rmd report, you will need to use params$report.data. Just using report.data will lead to the following error: object 'report.data' not found.

---
output: word_document
params:
report.data: NULL
---

```{r}
report.data <- params$report.data
# ...
```

Fix the path to the generated file

You are knitting the Rmd inside the temporary directory, which is generally a good idea. However, getting the paths right is not always that easy. In your case, I used the following

rendered_report <- rmarkdown::render(
tempReport, output_file = "wordreport.doc",
params = params,
envir = new.env(parent = globalenv())
)
file.copy(rendered_report, file)

The reason your version didn't work is that the generated report is created inside the temporary directory alogside tmpReport. See the reference documentation of ?rmarkdown::render for more details.

I used the return value of rmarkdown::render() instead which holds an absolute path to the generated file. This is less error prone and especially useful if you do not know the file extension of the generated file in advance

Use read.csv to convert the uploaded file into a data.frame

Shiny doesn't automatically convert uploaded csv files into dataframes. You need to define a parsing logic to do that.

params <- list(report.data = read.csv(input$file1$datapath))

One final word

Try to get more organized with your coding projects and limit the scope of future SO questions to one issue at a time. Creating "minimal reproducible examples" might seem tedious at first, but there are several advantages in doing that

  • Other people can read the questions and answers and reuse them in their own projects easily without dissecting a wall of code
  • It is much easier to answer those questions. With questions like this, the SO community usually only provides comments because answering them properly requires a lot of effort
  • Minimizing and isolating problems is a skill that will help you to figure out issues in your future coding projects much more easily


Related Topics



Leave a reply



Submit