R Shiny: Download Existing File

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 of ls inside the zip::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



Leave a reply



Submit