rstudio / shiny

Easy interactive web applications with R
http://shiny.rstudio.com
Other
5.35k stars 1.87k forks source link

`downloadhandler` function executed twice in RStudio Mac browser #1862

Open dracodoc opened 6 years ago

dracodoc commented 6 years ago

When running a Shiny app in RStudio Mac, the content function in downloadhandler will execute twice.

In my app I dynamically generate some files and pack them into zip when user clicked a download button. This behavior caused the files to be generated twice.

This only apply to the RStudio builtin shiny browser(safari). The Mac Safari and Chrome don't have this problem.

There are some other random bugs, when the download process will actually start a new app instance (in Mac Safari) or download a html which is just app html (in Mac Chrome). That was not easily reproducible but should be relate to this bug.

To test the behavior, just add these two line in the download example:

    content = function(file) {
      cat("content function started\n")
      write.csv(datasetInput(), file, row.names = FALSE)
      cat("content function ended\n")
    }
> runApp('shiny/download_handler')

Listening on http://127.0.0.1:4882
content function started
content function ended
content function started
content function ended

> sessionInfo()
R version 3.4.1 (2017-06-30)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS Sierra 10.12.2

Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.4/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
wch commented 6 years ago

This sounds like an issue with the Mac version of the IDE (I've tested on 1.1.374). On Windows, the problem doesn't seem to happen.

@jmcphers, @kevinushey, is there an existing issue for this for the IDE?

Here's a reproducible example:

library(shiny)

shinyApp(
  fluidPage(
    downloadButton("downloadData", "Download")
  ),
  function(input, output) {
    output$downloadData <- downloadHandler(
      filename = "mtcars.csv",
      content = function(file) {
        cat("content function started\n")
        write.csv(mtcars, file, row.names = FALSE)
        cat("content function ended\n")
      }
    )
  }
)
kevinushey commented 6 years ago

It looks like the content function gets triggered twice: once, when the Download button is clicked (I believe this is expected), and then a second time after the download is complete (unexpected).

It seems like this only occurs if you're interacting with the Shiny application from the Viewer pane; it doesn't occur if the application is opened in a separate browser window.

I also notice that RStudio opens a separate RStudio window, and the download appears to be initiated from there (?). If you cancel the download, the contents of mtcars show up in that window (but the content function is only triggered once).

I'll file this on the IDE side and we'll see if we can figure out what's going on. FWIW the same issue reproduces with RStudio v1.0 so I suspect this has been a long-running issue.

kevinushey commented 6 years ago

It looks like we didn't have an existing issue for this on the IDE side, so I've filed it there. We'll loop back in after we've figured out what's going on. Thanks for reporting!

dracodoc commented 6 years ago

Yes it's limited to RStudio Mac builtin browser (an older version of safari or webkit?).

I'm not sure which execution is expected though. The 1st time is before confirming a file name. If it's intended to

  1. write to a temporary file
  2. copy to the user confirmed file path

then this is correct. Otherwise if it's intended to

  1. user confirm a file path
  2. write file content to that path

then the 1st execution is redundant.

dracodoc commented 6 years ago

RStudio windows seemed cannot take the file parameter value, the default file name is the output slot name instead. Is this a known limitation?