R Shiny: Download existing file
After poking around with different file handling functions I discovered that file.copy
can be used to download the file.
I change downloadHandler
to:
output$downloadData <- downloadHandler(
filename <- function() {
paste("output", "zip", sep=".")
},
content <- function(file) {
file.copy("out.zip", file)
},
contentType = "application/zip"
)
Shiny Download File based on File Path
Thank you to everyone who commented and clarified my thinking a bit on how the download handler works.
In the end, i created a new function which split up the export function above
The new function i used is called generate_file()
which simply returns the file name
generate_file_name <- function(selection) {
# Create The file Name
filename <- paste(selection, Sys.Date(), sep = " - ") %>%
paste(.,"xlsx", sep = ".")
# removes the % sign and extra qoutes
filename <- gsub (pattern = '\'|%','', x = filename)
# output directory
myoutput <- paste('/home/shiny_tutorials/Save to Database/output/',
filename, sep = '')
# Return File Path
myoutput
}
Then in the server side
output$downloadRpt <- downloadHandler(
filename = function() {
selection <- input$company
generate_file_name(selection)
},
content = function(file) {
mydf <- report()
dateRange <- input$dates_report
selection <- input$company
export_report(mydf,selection,dateRange)
myfile <- generate_file_name(selection)
file.copy(myfile, file)
}
)
This then finds the newly created file and exports it for the user
Shiny download file not working
Solved it as follows:
UI.R
tabItem(tabName = "Downloads",
selectInput("filenames", "Choose a document to download:",list.files(path="/srv/shiny-server/apps/files")),
downloadButton('downloadData', 'Download'))
Server.R
output$downloadData <- downloadHandler(
filename = function() {
paste(input$filenames, sep='')
},
content = function(file) {
myfile <- paste0('/srv/shiny-server/apps/files/',input$filenames, collapse = NULL)
file.copy(myfile, file)
}
)
Download files (any kind) from server to local through Shiny
You can do this with a normal download button as suggested by @Sumedh
ui.R
downloadButton("demo", "Download")
server.R
output$demo <- downloadHandler(
filename = function(){
paste("demo","txt",sep=".")
},
content = function(con){
file.copy("some-file.txt", con)
})
download binary file from shiny server
I found the right function (file.copy) and after some trial and error figured out how to use it
# get info from input file uploaded by the user
BamFile <- reactive({
file <- input$BAM
req(file)
fpath <- file$datapath
fext <- tools::file_ext(fpath)
validate(need(fext %in% c("bam", "BAM"), "Upload must be a .bam or .BAM file"))
res <-
list(
upath = file$datapath,
fname = basename(file$name),
fext = fext
)
return(res)
})
....
# user wants to download the filtered bam file created by the shiny app
# the file was created in uploads='Uploads/' under the name 'data_filtered.bam'
output$downloadBam <- downloadHandler(
filename = function() {
gsub(".bam", "_filtered.bam", BamFile()$fname)
},
content = function(file) {
serverfile <- paste0(uploads,"/data_filtered.bam")
file.copy(serverfile, file)
}
)
How to download multiple files from R/Shiny app?
A few things edited and it's working:
- using
dir
instead ofls
inside thezip::zip
call to show the contents of the temp directory (ls
lists R environment rather than directory contents) - as a further suggestion: making a new, unique folder inside
tempdir()
to ensure only relevant files are added.
library(shiny)
library(glue)
library(tidyverse)
# Define UI for application
ui <- fluidPage(
# Application title
titlePanel("Test Multi-File Download"),
p("I hope this works!"),
downloadButton(
outputId = "download_btn",
label = "Download",
icon = icon("file-download")
)
)
# Define server logic
server <- function(input, output) {
#datasets stored in reactiveValues list
to_download <- reactiveValues(dataset1 = iris, dataset2 = airquality, dataset3 = mtcars, dataset4 = NULL)
blahblah <- iris
output$download_btn <- downloadHandler(
filename = function(){
paste("my_data_", Sys.Date(), ".zip", sep = "")
},
content = function(file){
temp_directory <- file.path(tempdir(), as.integer(Sys.time()))
dir.create(temp_directory)
reactiveValuesToList(to_download) %>%
imap(function(x,y){
if(!is.null(x)){
file_name <- glue("{y}_data.csv")
readr::write_csv(x, file.path(temp_directory, file_name))
}
})
zip::zip(
zipfile = file,
files = dir(temp_directory),
root = temp_directory
)
},
contentType = "application/zip"
)
}
shinyApp(ui = ui, server = server)
In my own Shiny app I had used a multi-worksheet approach as you suggested above. An alternative setup which works to produce a multi-sheet xlsx workbook using openxlsx
could be:
...
output$download_btn <- downloadHandler(
filename = function(){
paste("my_data_", Sys.Date(), ".xlsx", sep = "")
},
content = function(file){
wb <- createWorkbook()
reactiveValuesToList(to_download) %>%
imap(function(x,y){
if(!is.null(x)){
addWorksheet(wb, sheetName = y)
writeData(wb, x, sheet = y)
}
})
saveWorkbook(wb, file = file)
},
contentType = "file/xlsx"
)
...
Created on 2021-12-16 by the reprex package (v2.0.1)
Related Topics
How to Write from R to the Clipboard on a MAC
How to Check the Existence of a Downloaded File
Ggplot2: Line Connecting the Means of Grouped Data
R: Find and Add Missing (/Non Existing) Rows in Time Related Data Frame
Apply Over Matrix by Column - Any Way to Get Column Name
Is Data Really Copied Four Times in R's Replacement Functions
R: How to Display Clustered Matrix Heatmap (Similar Color Patterns Are Grouped)
Weighted Pearson's Correlation
Plot Mean and Sd of Dataset Per X Value Using Ggplot2
How to Avoid Using Round() in Every \Sexpr{}
Centering Image and Text in R Markdown for a PDF Report
R: Using Rgl to Generate 3D Rotatable Plots That Can Be Viewed in a Web Browser
Plotting Envfit Vectors (Vegan Package) in Ggplot2