Hi,
In my app, I automatically create a log file in the background of each app run, with a brief description of each action that is taken and when written to a text file using cat(). This serves as a record of what was done in the app in case the user wants to double-check, understandable with no R knowledge. See below for example code and output.
My question is twofold and mainly concerns downloadHandler(). As it is now, my log file is updated as soon as the download button is pressed, regardless of whether the file is actually saved or not. So if the user clicks save, but then cancels out of the Save File window instead of actually saving the file, the call to cat() is still carried out and the log file is still written as if the file had been saved, although the user cancelled the process.
I'm looking for a way to modify this so that the cat() call is conditional on a completed file save. Does anyone know a way to check whether the file generated by downloadHandler() is actually created and saved?
All I can think of is to check whether the final file is actually present using file.exists() (I tried making it conditional on the presence of the temp file, but this also didn't work). However, I haven't been able to figure out how to extract the user-defined file name and save location from the File Save window opened by downloadHandler(). Is there a way to write the chosen filename and folder location to a variable inside the app, so I could for example use file.exists() to check for it?
This would also be useful info to add into the log file itself, e.g. "Save data to example_folder/example_data.csv" instead of just "Save data".
Many thanks in advance for any suggestions!
(Also this is my first post, so I hope everything makes sense and please let me know if I should do something differently!)
Example app: (will create a directory called logs/ in your working directory, and save log files there)
library(shiny)
shinyApp(
ui = fluidPage(
actionButton("make_df",label="Generate DF"),
tableOutput("preview_df"),
downloadButton("download_df","Download DF")
),
server = function(input, output, session){
# Create a directory to store log files in
if(!dir.exists("./logs")) dir.create("./logs")
# File path for the log file for the current session
logfile <- paste0("logs/logfile_",format(Sys.time(),"%Y%m%d_%H-%M-%S"),".txt")
# Initiate log file for this session
file.create(logfile)
# Create dataframe
dat <- eventReactive(input$make_df,{
# Write record to logfile that you created a dataframe
cat(paste0(Sys.time(),"\nGenerate random dataframe","\n"),file=logfile,append=T)
# Actually create the dataframe
data.frame("A"=rnorm(10),"B"=rnorm(10))
})
# Show DF in app
output$preview_df <- renderTable(dat())
# Download DF
output$download_df <- downloadHandler(
filename = "example_df.csv",
content = function(file) {
# Write CSV
write.csv(dat(), file, row.names=F)
# Write record to logfile that you are saving the CSV
cat(paste0(Sys.time(),"\nSave dataframe","\n"),file=logfile,append=T)
}
)
}
)
Example output: (Generated by a portion of my actual app, not the above reprex, to demonstrate the use of such a logfile in slightly more complex apps)
logfile_20220216_12-46-01.txt
2022-02-16 12:46:10
Read in CSV data
2022-02-16 12:46:15
Log-transform data
2022-02-16 12:46:17
Remove duplicate entries
2022-02-16 12:46:25
Save modified DF