Timmwardion
Timmwardion

Reputation: 63

R/Shiny Download Handler Results in trunctated .csv file

I have built an application that stores a data frame in a reactive value. I then have a UI download button which downloads that data frame into a CSV file. It works well until the CSV file gets really big. I'd estimate around 100MB but it's hard to be sure.

My code is unremarkable - but a minimal reproducible example might be as follows. Seems that there may be a difference from running it locally and running it in on my Shiny Server instance (Amazon EC2).

ui.R

shinyUI(downloadButton("goDownload","Download Large File"))

server.R

library(shiny)

shinyServer(function(input, output, session) {

 op <- reactiveValues(data = NULL)

op$dataOp<-data.frame(col1=seq(0:30000000),col2=seq(30000000:0)

dataOp <- reactive({
  if (!is.null(op$dataOp)){
    op$Labels
  } else {
    print("no op$dataOp")
  }
  })


output$goDownload<- downloadHandler(
    filename = function() { paste('Data.csv', sep='') },
    content = function(filename) {
      write.csv(dataOp(), filename, row.names = F)
    })

})

Upvotes: 3

Views: 1122

Answers (1)

Chris
Chris

Reputation: 1615

My best guess is that you're not waiting long enough for shiny to finish writing the file to disk. It takes R a good amount of time to write large files (the data frame you gave takes somewhere between 30-60 seconds to write).

Another thing to be aware of is that shiny doesn't write directly to the file you give it in filename. Instead, it writes the data into a temp file and then copies that tempfile to filename....Both of these steps take time, so you have to leave the session open while R does its thing. The example below works for me.

library(shiny)

ui <- fluidPage(
  downloadButton("big_download", "Download Large File"),
  downloadButton("small_download", "Download small File")
)

server <- shinyServer(function(input, output, session) {

  big_data <- data.frame(col1 = seq(0:30000000), col2 = seq(30000000:0))
  small_data <- mtcars

  output$big_download <- downloadHandler(
    filename = function() {
      "big-data.csv"
    },
    content = function(filename) {
      print("writing data to tempfile")
      write.csv(big_data, filename, row.names = F)
      print("finished writing to tempfile, now copying it")
    }
  )

  output$small_download <- downloadHandler(
    filename = function() {
      "small-data.csv"
    },
    content = function(filename) {
      write.csv(small_data, filename, row.names = F)
    }
  )

})

shinyApp(ui, server)

Upvotes: 1

Related Questions