Plot reactive expression does not work within downloadHandler()

Hello, I want to include the option of download the plot in my shiny application. With the next code downloadHandler() just generates a white image:

library(shiny)

ui <- fluidPage(
  textInput("main", "Main title"),
  plotOutput("plot", height = 700),
  radioButtons("format", "Choose format", c("png", "jpeg", "pdf"), inline = TRUE),
  downloadButton("download", "Download image")
)

server <- function(input, output, session) {
  
  x <- 1:10
  y <- 1:10
  
  make_plot <- reactive(
    plot(x, y, main = input$main)
    )
  
  output$plot <- renderPlot(make_plot(), res = 96)
  
  output$download  <- downloadHandler(
    filename = function() {
      paste(Sys.Date(), "example_plot", input$format, sep = ".")
    },
    content = function(file) {
      if (input$format == "png") {
        png(file)
      } else if (input$format == "jpeg") {
        jpeg(file)
      } else {
        pdf(file)
      }
      make_plot()
      dev.off()
    }
  )
  
}

shinyApp(ui, server)

To overcome this behaviour, replacing the reactive expression within downloadHandler() by the plot function itself will be made the job as in the next code:

library(shiny)

ui <- fluidPage(
  textInput("main", "Main title"),
  plotOutput("plot", height = 700),
  radioButtons("format", "Choose format", c("png", "jpeg", "pdf"), inline = TRUE),
  downloadButton("download", "Download image")
)

server <- function(input, output, session) {
  
  x <- 1:10
  y <- 1:10
  
  make_plot <- reactive(
    plot(x, y, main = input$main)
    )
  
  output$plot <- renderPlot(make_plot(), res = 96)
  
  output$download  <- downloadHandler(
    filename = function() {
      paste(Sys.Date(), "example_plot", input$format, sep = ".")
    },
    content = function(file) {
      if (input$format == "png") {
        png(file)
      } else if (input$format == "jpeg") {
        jpeg(file)
      } else {
        pdf(file)
      }
      plot(x, y, main = input$main)
      dev.off()
    }
  )
  
}

shinyApp(ui, server)

The previous solution will increase the redundancy in the code. Any thoughts to avoid this?

Thanks a lot!

Hello! Unfortunately I have no explanation why this happens and am surprised myself, but I guess it might have something to do with how png(file) make_plot() dev.off() interact.

Thus, I have sadly not been able to find a base R solution for the problem, but employing ggplot2::qplot() for make_plot() and ggplot2::ggsave() in the downloadHandler() solved the issue on my end. I hope this helps.

library(shiny)

ui <- fluidPage(
  textInput("main", "Main title"),
  plotOutput("plot", height = 700),
  radioButtons("format", "Choose format", c("png", "jpeg", "pdf"), inline = TRUE),
  downloadButton("download", "Download image")
)

server <- function(input, output, session) {
  
  x <- 1:10
  y <- 1:10
  
  make_plot <- reactive({
    p <- ggplot2::qplot(x, y, main = input$main)
    p
    })
  
  output$plot <- renderPlot(make_plot(), res = 96)
  output$download  <- downloadHandler(
    filename = function() {
      paste(Sys.Date(), "example_plot", input$format, sep = ".")
    },
    content = function(file) {
     ggplot2::ggsave(plot = make_plot(), filename = file, device = input$format)
    }
  )
  
}

shinyApp(ui, server)

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.