Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R Shiny: async downloadHandler

I have a shiny app which takes a large amount of time downloading zip files. I am trying to use the futures and promises packages to manage the downloads so that other users can access the app while downloads are in progress.

The app looks as below:

library(shiny)

ui <- fluidPage(
  downloadButton("Download", "Download")
)


server <- function(input, output){
  output$Download <- downloadHandler(
    filename = "Downloads.zip",
    content = function(file){
      withProgress(message = "Writing Files to Disk. Please wait...", {
        temp <- setwd(tempdir())
        on.exit(setwd(temp))
        files <- c("mtcars.csv", "iris.csv")

        write.csv(mtcars, "mtcars.csv")
        write.csv(iris, "iris.csv")



        zip(zipfile = file, files = files)
      })
    }
  )
}

shinyApp(ui, server)

I've tried wrapping the write.csv inside a future function and setting `and while this does not throw an error, the app is not available for other users during the download.

library(shiny)
library(promises)
library(future)
plan(multiprocess)

ui <- fluidPage(
  downloadButton("Download", "Download")
)


server <- function(input, output){
  output$Download <- downloadHandler(
    filename = "Downloads.zip",
    content = function(file){
      withProgress(message = "Writing Files to Disk. Please wait...", {
        temp <- setwd(tempdir())
        on.exit(setwd(temp))
        files <- c("mtcars.csv", "iris.csv")

        future(write.csv(mtcars, "mtcars.csv"))
        future(write.csv(iris, "iris.csv"))



        zip(zipfile = file, files = files)
      })
    }
  )
}

shinyApp(ui, server)

I've also tried wrapping the entire downloadHandler function inside the future function, but I get the error:

Error in .subset2(x, "impl")$defineOutput(name, value, label) :
Unexpected MulticoreFuture output for DownloadUnexpected MultiprocessFuture output for DownloadUnexpected Future output for DownloadUnexpected environment output for Download

How can I handle the entire downloadHandler asyncronously? I am using the open source version of shiny server.

like image 967
Joseph Kigotho Avatar asked Nov 26 '18 09:11

Joseph Kigotho


1 Answers

Don't know if you still need an answer for this, but I think you were very close. I have wrapped both the write.csv and zip in future as below and it works for multiple users on my testing.

library(shiny)
library(promises)
library(future)
plan(multiprocess)

ui <- fluidPage(
  downloadButton("Download", "Download")
)


server <- function(input, output){
  output$Download <- downloadHandler(
    filename = "Downloads.zip",
    content = function(file){
      withProgress(message = "Writing Files to Disk. Please wait...", {
        temp <- setwd(tempdir())
        on.exit(setwd(temp))
        files <- c("mtcars.csv", "iris.csv")

        future({

        Sys.sleep(15)  
        write.csv(mtcars, "mtcars.csv")
        write.csv(iris, "iris.csv")



        zip(zipfile = file, files = files)})
      })
    }
  )
}

shinyApp(ui, server)
like image 188
tigerloveslobsters Avatar answered Oct 16 '22 14:10

tigerloveslobsters