Search code examples
rshinydownloadpngggsave

Unable to download a .png file from shiny


I'm trying to create a download button for my histogram plot. I have the download button visible, but can't seem to get it to download correctly. It always downloads a .htm file and not the .png file. I"m using the ggsave command in my server.R. I tried using the more traditional method, but that didn't seem to work either.

library(shiny)
library(plyr)
library(ggplot2)

shinyUI(fluidPage(
  headerPanel(title = "Test"),
  sidebarLayout(
    sidebarPanel(
      sliderInput("input.a", "A", min = 0, max = 100, value = 50),
      sliderInput("input.b", "B", min = 0, max = 100, value = 50),
      sliderInput("input.c", "C", min = 0, max = 100, value = 50)
    ),

    mainPanel(

      tabsetPanel( type = "tabs", #Open panel
                   tabPanel("Distributions",plotOutput("hist.plot")),
                   downloadButton('downloadhist', 'Download Plot'))

) # close mainPanel
) # close sidebarLayout
) # close fluidPage
) # close shinyUI

shinyServer(function(input,output){ # open shiny server

    #output$hist.plot = renderPlot({ # open renderPlot
    make.hist.plot = reactive({

    a = runif(1000,1,(input$input.a))
    b = runif(1000,1,(input$input.b))
    c = runif(1000,1,(input$input.c))

    amount = c(a,b,c)

    cat = c(rep("a",1000), rep("b",1000), rep("c",1000))

    hist.data = data.frame(amount,cat)
    names(hist.data) = c("amount","cat")

    hist.data$cat = factor(hist.data$cat, levels = c("a","b","c"))
    pricedata = ddply(hist.data, c("cat"), summarize, avg = mean(amount), minus.stdev = mean(amount)-sd(amount),
                      plus.stdev = mean(amount) + sd(amount))
    pricedata = pricedata[order(pricedata$avg),]


    ggplot(hist.data, aes(x=amount, fill = cat))+
      geom_histogram(color="white", alpha = .8, position = 'identity', binwidth = 5)+
      theme_test()+
      geom_vline(aes(xintercept = avg), data = pricedata, color = "black", size = 1)+


      geom_vline(aes(xintercept = minus.stdev), data = pricedata, color = "black", size = .75, linetype = "dotted")+


      geom_vline(aes(xintercept = plus.stdev), data = pricedata, color = "black", size = .75, linetype = "dotted")+


      facet_grid(cat ~., scales = "free")+
      scale_y_continuous(expand = c(0,0),name = "Count")+
      scale_x_continuous(labels = scales::dollar, name="\nAmount", limits = c(0,100))

  }) #close renderPlot

   output$hist.plot = renderPlot({
    print(make.hist.plot())
   })

    output$downloadhist = downloadHandler(
      filename = function() { "hist.png" },
      content = function(file) {
        ggsave(file, plot = make.hist.plot(), device = "png")}
    )

}) # close shinyServer




Solution

  • This seems to be an issue of scope. Your code does work if you put the download button in the sidebar panel, if you remove the tabsetPanel, or if you put the download button in the same tabPanel. The last solution is shown below:

    mainPanel(
      tabsetPanel( type = "tabs", #Open panel
        tabPanel("Distributions",
          plotOutput("hist.plot"),
          downloadButton('downloadhist', 'Download Plot')
        )
      )
    ) # close mainPanel