shiny icon indicating copy to clipboard operation
shiny copied to clipboard

Download handler downloads some "download.html" with the current page's HTML code

Open bersbersbers opened this issue 2 years ago • 12 comments

(I am not sure this is an issue with Shiny or Shiny Server - it might be the latter as I cannot reproduce it locally.)

System details

Browser Version: Windows and Linux, Chrome 100 and Firefox

Steps to reproduce the problem

  1. Visit https://shiny.rstudio.com/gallery/file-download.html
  2. Reload page
  3. Quickly click "Download"

chrome_f0bP4kXCd3

(In the video, I clicked twice - the first download is incorrect, the second download is correct.)

Describe the problem in detail

Some "download.html" file is downloaded, see download.html.txt.

I see this problem a lot when automating a Shiny app with Selenium, and have also come across it in manual app use. Apparently, it is not enough to wait for the download button to become clickable. Can I modify the Shiny app to prevent this issue? Is there any other state change that I can reliably wait for in Selenium to ensure that the download will succeed?

bersbersbers avatar Mar 30 '22 19:03 bersbersbers

Thank you for the reprex. I am able to reproduce the bug using the example link.

schloerke avatar Mar 31 '22 14:03 schloerke

I have the same issue -> downloading of download.html instead of csv file.

demydd avatar Jun 23 '22 19:06 demydd

I am having the same issue as well. Has there been any fix? I am using shiny version 1.7.2

tnguyenqh avatar Oct 12 '22 22:10 tnguyenqh

If you're seeing it while your app is first loading, there's not a fix (though we should totally fix it, it's so stupid and probably not that hard to fix). If you're seeing it in your app regardless of timing, it's likely your output$outputname <- downloadHandler is using an incorrect value for outputname.

jcheng5 avatar Oct 12 '22 22:10 jcheng5

Was there any update to the situation? Or is there any workaround that exists?

damienaymon avatar Feb 09 '23 11:02 damienaymon

I couldn't find anything either...

HassanMasoomi avatar Feb 09 '23 17:02 HassanMasoomi

I ran into this as well, really annoying.

I've posted a workaround here: https://gist.github.com/erikvona/96f0333704819ca242a9aed6cf07c07b but it's rather complex.

erikvona avatar Mar 07 '23 16:03 erikvona

I'm having the same problem too, although I am just learning shiny, so it could be an error I'm making myself

samsiljee avatar Apr 14 '23 04:04 samsiljee

I faced the same issue while having download button within initially hidden sidebar. I suspect this might be connected to Shiny's optimization for rendering hidden outputs (display: none css property exactly).

You can exclude an output from this behavior by setting up suspendWhenHidden = FALSE output option (having this option set I've managed to solve the issue in my app).

In case of the demo app, this would be:

  output$downloadData <- downloadHandler(
    filename = function() {
      paste(input$dataset, ".csv", sep = "")
    },
    content = function(file) {
      write.csv(datasetInput(), file, row.names = FALSE)
    }
  )
  outputOptions(output, "downloadData ", suspendWhenHidden = FALSE)

krystian8207 avatar Jun 29 '23 12:06 krystian8207

Having the same issue with an app that used to work great before, has anything change to the shiny architecture that is producing this?

gabrielascui avatar Sep 12 '23 07:09 gabrielascui

If you're seeing it while your app is first loading, there's not a fix (though we should totally fix it, it's so stupid and probably not that hard to fix). If you're seeing it in your app regardless of timing, it's likely your output$outputname <- downloadHandler is using an incorrect value for outputname.

Hi @jcheng5 I am wondering if you can expand on this "when app is first loading, download can fail" thing? I have a feeling this could be the root cause of an issue I am having: https://github.com/rstudio/shiny/issues/3748#issuecomment-1758593149

tylerlittlefield avatar Oct 12 '23 15:10 tylerlittlefield

  outputOptions(output, "the_button_id", suspendWhenHidden = FALSE)

This works with shiny_1.8.0 !

trafficonese avatar Nov 23 '23 12:11 trafficonese

Hi, all.

This post isn't related to the bug noted above, but I stumbled onto this thread while troubleshooting and thought someone else might too.

I'm posting this for anyone using the Rhino framework who is encountering the problem of downloadHandler outputting HTML vs CSV "regardless of timing" as Joe Chang mentioned above.

Something about Joe's below comment got me thinking there was something wrong with downloadButton.

output$outputname <- downloadHandler using an incorrect value for outputname

I tried outputOptions(output, "downloadData", suspendWhenHidden = FALSE) as mentioned by someone else above and the output message was an error stating the output ID couldn't be found, which was strange since the ID was defined in the downloadButton outputId arg.

Takeaway: if you're using the Rhino framework remember that outputIDs must be enclosed by ns() otherwise output$output_name won't be found. Once the downloadButton outputId arg was encapsulated with ns() downloadHandler worked as expected, it output a CSV.

outputOptions(output, "download_data", suspendWhenHidden = FALSE)

Error in .subset2(x, "impl")$outputOptions(name, ...) : 
  app-main-download_data  is not in list of output objects
# wrong
downloadButton(
  outputId = "download_data",
  label = "Download",
  icon = icon(name = "download", verify_fa = FALSE)
)

# right
downloadButton(
  outputId = ns("download_data"),
  label = "Download",
  icon = icon(name = "download", verify_fa = FALSE)
)

SaintRod avatar Mar 01 '24 16:03 SaintRod

@SaintRod

Could you please try outputOptions(output, "downloadData", suspendWhenHidden = FALSE)? I've accidentally added space within the id ("downloadData ") in my previous answer, I suppose this is why you've got such errors.

krystian8207 avatar Mar 05 '24 20:03 krystian8207

@krystian8207 good catch, but I didn't use "downloadData " as the argument value. My outputID is "download_data". I've updated the reference to your original post to remove the space and the argument name in the code block. The error, in hindsight, was expected because when creating apps using the Rhino framework outputIDs [within a module] must be enclosed by ns(), which I omitted originally.

SaintRod avatar Mar 05 '24 21:03 SaintRod

@SaintRod Thank for your comment, I also use Rhino, but this didnt help.

Could you please compare my code to yours? maybe you will catch something

#' @export ui <- function(id) { ns <- NS(id) downloadButton( ns("download_data"), label = "download", icon = icon("download", verify_fa = FALSE) ) }

#' @export server <- function(id, data) { moduleServer(id, function(input, output, session){ data <- reactive({data()})

output$download_data <- downloadHandler(
  filename = "data.csv",
  content = function(filename) {
    write.csv(data(), filename, row.names = FALSE)
  }
)

outputOptions(output, "download_data", suspendWhenHidden = FALSE)

})}

Thank you

Arnold-Kakas avatar Mar 09 '24 19:03 Arnold-Kakas

@Arnold-Kakas

I don't know for certain what the issue is with your code. I'd recommend to add the error message to your post. However, at a glance I think one issue is the filename argument in downloadHandler should be a function. For example, as can be seen above:

  output$downloadData <- downloadHandler(
    filename = function() {
      paste(input$dataset, ".csv", sep = "")
    },
    content = function(file) {
      write.csv(datasetInput(), file, row.names = FALSE)
    }
  )
  outputOptions(output, "downloadData ", suspendWhenHidden = FALSE)

SaintRod avatar Mar 10 '24 02:03 SaintRod

@SaintRod I tried it with function but it does not work either :/ what do you mean by error message? I dont get any error, the code just downloads htm file

Arnold-Kakas avatar Mar 10 '24 07:03 Arnold-Kakas

@Arnold-Kakas

Could you please try this example:

library(shiny)
ui <- function(id) {
  ns <- NS(id)
  downloadButton(
    ns("download_data"),
    label = "download",
    icon = icon("download", verify_fa = FALSE)
  )
}

server_mod <- function(id, data) {
  moduleServer(id, function(input, output, session){
    #data <- reactive({data()})
    
    output$download_data <- downloadHandler(
      filename = "data.csv",
      content = function(filename) {
        write.csv(data(), filename, row.names = FALSE)
      }
    )
    
    outputOptions(output, "download_data", suspendWhenHidden = FALSE)
  })}

server <- function(input, output, session) {
  data <- reactive(mtcars)
  server_mod("mod", data)
}

shiny::shinyApp(ui("mod"), server)

I'm not sure how you call the module, but in the above example commenting out data <- reactive({data()}) within a module helped to download the csv. Having this line uncommented I got:

Warning: Error in : C stack usage  7976452 is too close to the limit
  3: runApp
  2: print.shiny.appobj
  1: <Anonymous>

and html file downloaded instead.

In fact you don't have to set outputOptions(output, "download_data", suspendWhenHidden = FALSE) in the example, csv still is downloaded correctly.

krystian8207 avatar Mar 10 '24 11:03 krystian8207

I updated the title of this issue to reflect the original post, which is related to app loading.

I was wondering if maybe the people who are discussing the unrelated issue of download issues after the app has finished loading (essentially, all comments after https://github.com/rstudio/shiny/issues/3606#issuecomment-1973471177) could find a better place to discuss this. It's noise to all those watching this to see when the original issue is resolved. Thank you.

bersbersbers avatar Mar 10 '24 12:03 bersbersbers