I have this shinyapp where I want to download a file via a button. So I can do this by calling a downloadHandler like:
output$downloadData <- downloadHandler(
filename = "plot1.png",
content = function(file) {
plotPNG(func = function(){
plot(some.Data)
},
filename = file,
width = 3000,
height = 2000,
res = 300
)
}
)
Here the file is downloaded into the default download directory. What now if I want to download into another dir? In other words: Is there a way to determine the default download dir and to manipulate that?
The downloadHandler() should be able to handle this problem. The filename argument is, "A string of the filename, including extension, that the user's web browser should default to when downloading the file.." Therefore we can manipulate the default directory by defining the path in the filename.
server<-function(input,output){
output$downloadData <- downloadHandler(
# Sets filename the browser should default too
filename = function() {
paste(PATH_TO_DIR,"plot1",".png/xls/etc.",sep="")
}, # Closes Filename Function
# Creates Download file
content = function(file) {
plotPNG(func = function(){
plot(some.Data)
},
file = filename(),
width = 3000,
height = 2000,
res = 300
)
}
ui<-
downloadButton("downloadData", 'Download File')
)
This can be used in co-op with a download button, and the name of the file and path can be dynamically generated when the button is pushed by defining the path with variables. I think this may open a file browser, and I do not know if this is avoidable.
Also note that the file name, path, and content type will not appear to work in a local session (RStudio), they only work once deployed in the browser.
Related
ref: How to download workbook via downloadHandler on Shiny?
** Workbook is already held in the app's directory**
Does anyone have experience with putting in a download link into a shiny app for an excel file held in the app's directory? I have an excel form that I need users to be able to download and use (it is specifically NOT a dataframe).
The following code worked for when I put in a powerpoint file in the downloadHandler function:
output$downloadinflationguidance <- downloadHandler(
filename = function() {
paste("www/inflation-guidance - ", Sys.Date(), '.pptx', sep='')
},
content = function(con) {
pptx <- read_pptx("www/inflation-guidance.pptx")
print(pptx, target = con)
}
)
But when I swap out the powerpoint stuff for the excel form (see below) it doesn't work. When I run the app and click on the download link, the user gets an error saying "file not found". The excel file is held locally on the app in a folder titled "www". Am I missing a trick here?
shinyUI(
downloadLink("dl_excel_calc", label = "Excel Version")
)
shinyServer(function(input, output, session) {
output$dl_excel_calc <- downloadHandler(
filename = function() {
paste0("indexation_tool_excel -", Sys.Date(), ".xlsx", sep='')
},
content = function(con) {
xlsx <- read_excel('indexation_tool_excel.xlsx')
print(xlsx, target = con)
}
)
}
I'm generating a powerpoint presentation in R using officer, and then converting this to a PDF so a user can preview slides inside the shiny golem app. But after referencing this thread and this SO answer to a similar question I'm still not quite sure how to accomplish this. I am able to display external PDFs located in inst/app/www inside an iframe, but not sure how to do this for PDFs generated inside the app itself.
Here is the relevant code snippet from my app_server.R file:
output$preview <- renderUI({
# Creates rpptx object with one slide
preview_rpptx <- add_title_slide(x = NULL, title = input_list[["title"]])
# Creates www/ directory if it doesn't exist
if (!dir_exists("www")) dir_create("www")
# Generates .pptx file
pptx_file_path <- file_temp("preview", tmp_dir = "www", ext = ".pptx")
print(preview_rpptx, pptx_file_path)
# Converts .pptx to .pdf
pdf_file_path <- file_temp("preview", tmp_dir = "www", ext = ".pdf")
convert_to_pdf(path = pptx_file_path, pdf_file = pdf_file_path)
tags$iframe(style = "height:600px; width:100%", src = str_sub(pdf_file_path, 5))
}
Running the app, I get a "Not Found" error inside the iframe. But I can see that the PDF file was generated properly in the www/ directory.
Since I don't know how to do with a file as you ask, I would encode this file to a base64 string and set this string to the src attribute:
library(base64enc)
output$preview <- renderUI({
......
pdf_file_path <- "PATH/TO/PDF_FILE"
b64 <- dataURI(file = pdf_file_path, mime = "application/pdf")
tags$iframe(
style = "height: 600px; width: 100%;", src = b64
)
}
I have a RShiny app where I fetch a zip file from a s3 bucket using aws.s3 library. I have a specific file within this zip archive that users will download upon clicking downloadButton.
Below is a snippet from my server part of the code
rvalues <- reactiveValues(r = file())
observe({
rvalues$r <- tempfile(fileext = paste0(".", tools::file_ext("MyArchive.zip")))
r <- save_object(bucket = MyBucket,
object = "MyArchive.zip",
file = rvalues$r,
key = accesskey,
secret = secretKey,
region = region)
})
output$download <- downloadHandler(
filename = function() {
"Sample.json"
},
content = function(file) {
unzip(rvalues$r,"Sample.json")
}
)
I am creating a temp file and saving the zip from s3 to this temp file. From this temp file, I am unzipping my specific file and passing it to the download handler function. For some reason, this doesn't work. Any help/guidance is much appreciated!
I would try the following code (I have not tried it since you don't provide a reproducible example):
output$download <- downloadHandler(
filename = function() {
"Sample.json"
},
content = function(file) {
filepath <- unzip(rvalues$r,"Sample.json")
file.copy(filepath, file)
}
)
I like to download a file in shiny which is created by base64enc::base64decode.
What I have so far is:
library(base64enc)
library(shiny)
downloadHandler(
filename = function()
"test.txt",
content = function(file) {
base64decode(what = "VGhpcyBpcyBhIHRlc3Qu", output = file)
}
)
and I get Warning: Error in file: argument "file" is missing, with no default
When I use base64decode without shiny, I use:
base_string <- "VGhpcyBpcyBhIHRlc3Qu"
o_file <- file("C:/User/Desktop/test.txt"), "wb")
base64decode(what = base_string, output = o_file)
close(o_file)
and everything works fine.
Is it possible to use the downloadHandler without executing the second statement first? I want to create the file just for the download.
If we look into the documentation of ?downloadHandler we see that the content parameter requires a file path (string) of a nonexistent temp file and writes the content to that file path.
If we look into the code of base64decode:
if (is.character(output)) {
output <- file(output, "wb")
on.exit(close(output))
}
we see that file() is called, so that you would create/open a connection to a file already and the condition of "non-existance" of that file wouldn´t be fulfilled (my understanding).
Maybe, you could use smthg like:
write.csv(base64decode(what = base_string), file)
Full app:
library(base64enc)
library(shiny)
ui <- fluidPage(
downloadLink("downloadData", "Download")
)
server <- function(input, output) {
# Our dataset
data <- mtcars
output$downloadData <- downloadHandler(
filename = function() {
paste("data-", Sys.Date(), ".stackoverflow", sep="")
},
content = function(file) {
base_string <- "VGhpcyBpcyBhIHRlc3Qu"
write.table(base64decode(what = base_string), file)
}
)
}
shinyApp(ui, server)
Edit: Given your question in the comment. You can use write.table() for an arbitrary file type. See the edited example above to write to a file of type .stackoverflow ;).
I have a reactive dataframe and I have the download handler working. I would like to access the filepath so I can reference the downloaded data without using the fileInput function. The code below works, however, I am trying to to grab the filepath so I can run a prewritten function on the downloaded csv file.
output$downloadData <- downloadHandler(filename =
function({paste(Sys.time(), ' Shiny File.csv', sep='') },
content = function(file) {write.csv(sample_data(),
file, row.names = FALSE)
})