Downloading a file generated by shiny - r

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

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

reactiveFileReader in Shiny will not update when new files are added to the reactive filePath

I am using the reactiveFileReader function in an R Shiny app to read in and visualize data that are being logged in real time (1 second data). The data files are being stored in a single folder but a new file is created every hour. I am using a reactive file path that should update when a new file is created and begin reading in and plotting data from the new file, however, reactiveFileReader does not seem to be reactive to changes in the filePath argument. The app just freezes at the last data point from the previous file until I refresh the whole app, at which time the new file is visualized.
Here is a snippet of the code I am using to read in the data.
dir <- "/media/sf_D_DRIVE"
file_name <- reactive({paste0(dir, "/", list.files(dir)[length(list.files(dir))])})
df_1 <- reactiveFileReader(intervalMillis = 100, session = session , filePath = file_name, readFunc = read.csv)
I've also tried putting the filePath directly as an argument.
dir <- "/media/sf_D_DRIVE"
df_1 <- reactiveFileReader(intervalMillis = 100, session = session , filePath = paste0(dir, "/", list.files(dir)[length(list.files(dir))]), readFunc = read.csv)
Does anyone have any thoughts on how to have the filePath update reactively and the app read and visualize data from the new files added to the folder without having to refresh?
Unfortunately, it is challenging to provide a reproducible example since you would need the data logging and file creation side of the example to make it work. Hopefully someone still has some ideas! Thanks!
reactiveFileReader is based on reactivePoll. You can use reactivePoll to achieve what you want:
df_1 <- reactivePoll(
1000, session,
checkFunc = function(){
# this function returns the most recent modification time in the folder
files <- list.files(dir, full.names = TRUE)
info <- file.info(files)
max(info$mtime)
},
valueFunc = function(){
# this function returns the content of the most recent file in the folder
files <- list.files(dir, full.names = TRUE)
info <- file.info(files)
i <- which.max(info$mtime)
read.csv(files[i])
}
)

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

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

How do you find filepath of the downloadHandler in Shiny?

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

Resources