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
Update an Entire Row in Data.Table in R
Finding the Index of First Changes in the Elements of a Vector
Shading Area Between Two Lines in R
How to Represent Polynomials with Numeric Vectors in R
Shiny - How to Change the Font Size in Select Tags
How to Select All Factor Variables in R
Why Do Rapply and Lapply Handle Null Differently
Plotly Adding a Source or Caption to a Chart
How to Plot Histogram/ Frequency-Count of a Vector with Ggplot
How to Add "Author" Metadata to a PDF Created from R
Copying List of Files from One Folder to Other in R
R: Save All Data.Frames in Workspace to Separate .Rdata Files
Can Transparency Be Used with Postscript/Eps
How to Convert Camelcase to Not.Camel.Case in R
In R: Joining Vector Elements by Row, Converting Vector Rows to Strings
Remove Multiple Patterns from Text Vector R
How to Flatten R Data Frame That Contains Lists
Ggplot2: How to Reduce Space Between Narrow Width Bars, After Coord_Flip, and Panel Border