How do you find filepath of the downloadHandler in Shiny? - r

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)
})

Related

How to create a download link in shiny for a local excel workbook (not dataframe) via downloadHandler

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)
}
)
}

Download a zip file and extract a specific file in Shiny App

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)
}
)

get download dir from browser

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.

R Shiny DownloadHandler + base64decode

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 ;).

Downloading a file generated by shiny

I'm trying to download a BSON file that I export to my shiny app from a MongoDB using the mongolite package. This is the code in my download button:
output$downloadTiming <- downloadHandler(
filename = "/keyTiming.bson",
content = function(fileToDownload){
mongolite::mongo(
collection = "keyTiming",
url = "mongodb://<User>:<Pass>#<url>"
)$export(fileToDownload, bson = TRUE)
}
)
When I try to download it, it says "Error: inherits(con, "connection") is not TRUE". I have spent a good amount of time researching and have found nothing, and hope that someone here can be of use.
I figured it out eventually. The final code looks like this
output$downloadTiming <- downloadHandler(
filename <- function(){
return("timingOut.bson")
},
content <- function(file){
outFile = file("timingOut.bson")
mongolite::mongo(
collection = "timings",
url = "mongodb://<user>:<pass>#<database>"
)$export(outFile, bson = TRUE)
file.copy("timingOut.bson", file, overwrite = TRUE)
}
)

Resources