Get filename from downloadHandler

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

in general you should assume you cant snoop on your users client machines, i.e. you can only know that your app responded to a request to serve up a file, you can't know that it is present on your users machine.

Perhaps there is some sophisticated javascript that might be employed to have the browser report its activities back to shiny but I wouldnt necessarily assume so.

I expect it might be considered a security violation, if you were able to see the paths on users machines where they had saved a file you app served up to them over the internet.

file 'example.txt' was saved in 'c:\users\JSmith\docs\John Smiths -holiday abroad for jul2022' sort of thing....

Ah that makes sense, so it probably just isn't possible then. Thank you!

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.