How to stop download in downloadHandler

This was a bit tricky but I think I have a solution using some CSS and JS.

The CSS styling hides the visibility of the actual downloadButton but it remains functional and accessible to client-side JS code.

Then I used an actionButton styled the same way as a download button to initiate an observeEvent block of code.

If your checks fail it will show the modal dialog, if they pass it will run some JS code using the shinyJS package to simulate a 'click' of the hidden download button and then the download handler code will run.

However this isn't a perfect solution in terms of security because the actual download link will be visible in the html page source code.

library(shiny)

ui <- fluidPage(
  shinyjs::useShinyjs(),
  actionButton("init", "Download", icon = icon("download")),
  downloadButton("downloadData", "Download", style = "visibility: hidden;")
)

server <- function(input, output) {
  # Our dataset
  data <- mtcars
  
  observeEvent(input$init, {
    if (TRUE) {
      showModal(
        modalDialog(
          title = 'Error',
          p('Hello world!')
        )
      )
    } else {
      shinyjs::runjs("document.getElementById('downloadData').click();")
    }
  })
  
  output$downloadData <- downloadHandler(
    filename = function() {
      paste("data-", Sys.Date(), ".csv", sep="")
    },
    content = function(file) {
      write.csv(data, file)
    }
  )
}

shinyApp(ui, server)
2 Likes