Downloading plots using downloadHandler()

11,025 views
Skip to first unread message

JBell

unread,
Dec 6, 2012, 12:51:48 PM12/6/12
to shiny-...@googlegroups.com
I'm building a shiny app which initially will have 4 tabs, each with different plots.  I'd like to give the user the option to download the plots as png or jpg files.  Can't seem to get this working, as I can't really pass "file" to png() or jpg().

server.R

output$downloadData.top6 <- downloadHandler(
    filename <- function() {
      paste(input$group,'-plot', Sys.Date(),'.png',sep='') },
    content <- function(file) {
      png(top6.plot(input$group))
      #png(file)
    },
    contentType = 'image/png'
)

ui.R

  mainPanel(
    tabsetPanel(
      tabPanel("top6.plot",h3(textOutput("query")), plotOutput("top6.plot"),
               downloadButton('downloadData.top6','Download Graph')),
...
...
....
..


Is this possible?  Any help greatly appreciated.

Joe Cheng

unread,
Dec 6, 2012, 5:27:52 PM12/6/12
to shiny-...@googlegroups.com
png takes a filename, then you plot, then you call dev.off:

png(file)
plot(...)
abline(...)
rect(...)
dev.off()

If that's not working then I think we would need to see your code for top6.plot.



--
 
 

JBell

unread,
Dec 7, 2012, 4:56:15 PM12/7/12
to shiny-...@googlegroups.com
Thank you Joe!  Worked like a charm.  Final code:


output$downloadData.top6 <- downloadHandler(
    filename <- function() {
      paste(input$group,'-top6_plot', Sys.Date(),'.png',sep='') },
    content <- function(file) {
      png(file, width = 980, height = 400, units = "px", pointsize = 12,
          bg = "white", res = NA)
      top6.plot <- top6.plot(input$group)
      print(top6.plot)
      dev.off()},
    contentType = 'image/png'
  )

I appreciate the help!

Gabriel Torres

unread,
Feb 8, 2013, 2:17:47 PM2/8/13
to shiny-...@googlegroups.com

Hi Joe,

I am trying to do some exporting buttons for my shiny app, but the file size is 0 bytes.

I have tried different things including your recommendations for Jbell.
my code for table (in red) is working perfect, but for the plot is not working;
(the file name is being exported correctly)

This is my code:

output$downloadData <- downloadHandler(
filename = function() {
paste("data", Sys.Date(), ".csv", sep="")
},
content = function(con) {
write.csv((cbind(Radius=seq(input$rad1,input$rad2),
                             ug.ul=Conc3())), con)
}
)

 
  output$downloadData.plot1 <- downloadHandler(
    filename <- function() {
      paste(input$product,input$ppm,"ppm", Sys.time(),'.png',sep='') },
  
content <- function(file) {

          png(file, width = 980, height = 400, units = "px", pointsize = 12,
          bg = "white", res = NA)
     y <-plot(1,1)
      print(y)
      dev.off()},
    contentType = 'image/png'
  )

Joe Cheng

unread,
Feb 8, 2013, 6:44:28 PM2/8/13
to shiny-...@googlegroups.com
Hi Gabriel,

  content = function(con)

needs to be

  content = function(file)

See ?downloadHandler for more details.


--
You received this message because you are subscribed to the Google Groups "Shiny - Web Framework for R" group.
To unsubscribe from this group and stop receiving emails from it, send an email to shiny-discus...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Gabriel Torres

unread,
Feb 8, 2013, 8:57:57 PM2/8/13
to shiny-...@googlegroups.com
Joe,  thanks for your answer,

I did the correction (con) for (file), however that was for the table and it is working properly.
my problem is saving the plots; as I mentioned before, when I try to save the plot

content = function(file) {
     png(file)
     plot(...)
     dev.off()

as you mentioned and as followed by JBell, the save window pop out, but the PNG file is displayed as 0 bytes; if I try to open the file I got an error message indicating that the file is empty.

as a temporary measure I create a folder within the folder ("plots"), where I have the ui and server files, and  create the following png statement:
 
      png(paste("plots/",input$product,input$ppm,"ppm",".png"))

What can I do to make it works (download a working file selecting a directory)?

Thanks

Gabriel

Winston Chang

unread,
Feb 11, 2013, 1:39:01 PM2/11/13
to shiny-...@googlegroups.com
Hi Gabriel -

I've modified the 10_download example, and this works:

  output$downloadData <- downloadHandler(
    filename = function() {
      paste(input$dataset, Sys.time(), '.png', sep='')
    },
     
    content = function(file) {
      png(file, width = 980, height = 400, units = "px", pointsize = 12, bg = "white", res = NA)
      plot(1,1)
      dev.off()
    },
    contentType = 'image/png'
  )


Note a couple differences:
* No need to do `y <- plot(1,1)` or `print(y)` for plot(), though something like that is needed if you use ggplot().

* Use `filename = function()` instead of `filename <- function()`. The latter may have worked, but only because it uses positional matching. It would also assign values to `function` and `content` in the parent environment. This will illustrate:

foo <- function(a, b) {
  cat("a=", a, "  b=", b, "\n", sep="")
}

foo(a <- 1, b = 2)
# a=1  b=2

a
# 1
b
# Error: object 'b' not found

# Reverse b and a
foo(b <- 1, a <- 2)
# a=1  b=2


veep...@gmail.com

unread,
Mar 8, 2013, 5:08:40 AM3/8/13
to shiny-...@googlegroups.com
Hi
Why this is not working?

library(shiny)
require(png)
# Define server logic required to generate and plot a random distribution
shinyServer(function(input, output) {    
  
  output$distPlot <- renderPlot({
    
    ############### 
    #Save the plot 
    ###############
    png("myplots.png")   
      y <- rnorm(50)
          plot(y)    
    dev.off() 
    ##########################
    #Read the plot for Display
    ########################## 
    
    output$downloadData <- downloadHandler(
      filename = function() {
        paste('myplots', '.png', sep='')
      },
      
      content = function(file) {
        png(file, width = 980, height = 400, units = "px", pointsize = 12, bg = "white", res = NA)
        plot(1,1)        
        dev.off()
      },
      contentType = 'image/png'
    )
    
    
  })
})


Thanks 
veepsirtt

Joe Cheng

unread,
Mar 8, 2013, 10:39:17 AM3/8/13
to shiny-...@googlegroups.com
What about it isn't working?
Sent from my phone

Velappan Periasamy

unread,
Mar 8, 2013, 11:01:07 AM3/8/13
to shiny-...@googlegroups.com
Hi  Joe Cheng
thanks
try this linkhttp://glimmer.rstudio.com/veepsirtt/myplot/


 #--------------
server.R
#-----------------
##########
library(shiny)
#require(ReadImages)
#require(animation)

require(png)
# Define server logic required to generate and plot a random distribution
shinyServer(function(input, output) {   
 
  output$distPlot <- renderPlot({
   
    ###############
    #Save the plot
    ###############
  
    png("myplots.png")  
      y <- rnorm(50)
          plot(y)   
    dev.off()
 
    ##########################
    #Read the plot for Display
    ##########################
    #library(EBImage)
    #x = readImage('myplots.jpg')
    #display(x)
    #system2(getOption("xpdf"), "myplots.pdf", wait = FALSE)
    #image(myplots.jpg)

    output$downloadData <- downloadHandler(
      filename = function() {
        paste('myplots.png', sep='')

      },
     
      content = function(file) {
        png(file, width = 980, height = 400, units = "px", pointsize = 12, bg = "white", res = NA)
        plot(1,1)
        print()

        dev.off()
      },
      contentType = 'image/png'
    )
   
   
  })
}

#-----------------

ui.R
#-------------------
library(shiny)

# Define UI for application that plots random distributions
shinyUI(pageWithSidebar(
 
  # Application title
  headerPanel("Hello Shiny!"),
 
  # Sidebar with a slider input for number of observations
  sidebarPanel(
    #sliderInput("obs",
              #  "Number of observations:",
              #  min = 0,
               # max = 1000,
                #value = 500),
    downloadButton('downloadData', 'Download')
   
   
  ),
 
  # Show a plot of the generated distribution
  mainPanel(
    plotOutput("distPlot")
  )
))
> sessionInfo()
R version 2.15.2 (2012-10-26)
Platform: x86_64-pc-linux-gnu (64-bit)

locale:
 [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C        
 [3] LC_TIME=C            LC_COLLATE=C        
 [5] LC_MONETARY=C        LC_MESSAGES=C       
 [7] LC_PAPER=C           LC_NAME=C           
 [9] LC_ADDRESS=C         LC_TELEPHONE=C      
[11] LC_MEASUREMENT=C     LC_IDENTIFICATION=C 

attached base packages:
[1] compiler  stats     graphics  grDevices utils     datasets 
[7] methods   base     

other attached packages:
 [1] EBImage_4.0.0       BiocInstaller_1.8.3 png_0.1-4          
 [4] rgdal_0.8-5         jpeg_0.1-2          raster_2.0-41      
 [7] sp_1.0-5            chron_2.3-43        quantmod_0.4-0     
[10] TTR_0.21-1          xts_0.9-3           zoo_1.7-9          
[13] Defaults_1.1-1      lattice_0.20-13     ggplot2_0.9.3.1    

loaded via a namespace (and not attached):
 [1] MASS_7.3-23        RColorBrewer_1.0-5 abind_1.4-0       
 [4] colorspace_1.2-0   dichromat_1.2-4    digest_0.5.2      
 [7] grid_2.15.2        gtable_0.1.1       labeling_0.1      
[10] munsell_0.4        plyr_1.7.1         proto_0.3-9.2     
[13] reshape2_1.2.1     scales_0.2.3       stringr_0.6.1     
[16] tiff_0.1-4         tools_2.15.2      

>




--
You received this message because you are subscribed to a topic in the Google Groups "Shiny - Web Framework for R" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/shiny-discuss/u7gwXc8_vyY/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to shiny-discus...@googlegroups.com.

Joe Cheng

unread,
Mar 8, 2013, 12:38:18 PM3/8/13
to shiny-...@googlegroups.com
You should not have the output$downloadData assignment nested inside the renderPlot call.

Also the empty print() statement inside the content function should be removed.

veep...@gmail.com

unread,
Mar 11, 2013, 1:41:42 AM3/11/13
to shiny-...@googlegroups.com
HI Joe Cheng,

my link 

http://glimmer.rstudio.com/veepsirtt/myplot/
Why the combined plots are not saved?

thanks
veepsirtt
..........................
library(shiny)
require(png)
# Define server logic required to generate and plot a random distribution
shinyServer(function(input, output) {    
  
  output$distPlot <- renderPlot({
    
    ############### 
    #Save the plot 
    ###############
    
    png("myplots.png") 
    par(mfrow=c(2,1))
      y1 <- rnorm(50)
          plot(y1)  
      y2 <- rnorm(100)
          plot(y2)
     
    dev.off() 
  
  })
  
  ##############################
  #Download the plot for Display
  ##############################
  
  
  output$downloadData <- downloadHandler(
    filename = function() {
      paste('myplots.png', sep='')
    },
    
    content = function(file) {
      png(file, width = 980, height = 400, units = "px", pointsize = 12, bg = "white", res = NA)
      plot(1,1) 
      dev.off()
    },
    contentType = 'image/png'
  )
  
})


To unsubscribe from this group and stop receiving emails from it, send an email to shiny-discuss+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 


--
Sent from my phone

--
You received this message because you are subscribed to a topic in the Google Groups "Shiny - Web Framework for R" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/shiny-discuss/u7gwXc8_vyY/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to shiny-discus...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.
 
 

Luca Fenu

unread,
Mar 12, 2013, 4:15:32 AM3/12/13
to shiny-...@googlegroups.com
Veep,

I can save your plots without any problem... Are you sure it's not a browser issue? (I'm on Chrome)

Luca

veep...@gmail.com

unread,
Mar 14, 2013, 12:13:14 PM3/14/13
to shiny-...@googlegroups.com
Hi Luca
try
http://glimmer.rstudio.com/veepsirtt/myplot/
How to increase the plot size to full screen?
thanks
veepsirtt

#....................................
server.R
#.....................................

shinyServer(function(input, output) {
  myplot <- function() {
    #par(mfrow=c(3,1))
    mat <- matrix(c(1,2,3), 3, 1, byrow = TRUE)
    nf <- layout(mat, widths = c(200, 200, 200), height = c(100,100,100 ), TRUE)
    layout.show(nf)

       
    y1 <- rnorm(50)   
      plot(y1)
    y2 <- rnorm(100)
      plot(y2)
    y3 <- rnorm(200)
      plot(y3) 
   
  }

  output$distPlot <- renderPlot({ myplot() })

  output$downloadData <- downloadHandler(
    filename = 'myplots.png',
    content = function(file) {
      png(file, width = 1000, height = 1000, units = "px", pointsize = 12, bg = "white", res = NA)
      myplot()

      dev.off()
    },
    contentType = 'image/png'
  )
})

#.....................
#  ui.R

#-------------------
library(shiny)

# Define UI for application that plots random distributions
shinyUI(pageWithSidebar(
 
  # Application title
  headerPanel("Hello Shiny!"),
 
  # Sidebar with a slider input for number of observations
  sidebarPanel(
    #sliderInput("obs",
              #  "Number of observations:",
              #  min = 0,
               # max = 1000,
                #value = 500),
    downloadButton('downloadData', 'Download')
  
  
  ),
 
  # Show a plot of the generated distribution
  mainPanel(
    plotOutput("distPlot")
  )
))




moggces

unread,
Dec 15, 2013, 12:20:32 PM12/15/13
to shiny-...@googlegroups.com
I tried to follow instructions in the posts but somehow I can still download a blank image.

I created a reactive function (select_plot) to generate plots.

select_plot <- reactive({
    showHeatmap <- input$showheat
    profileType <- input$proftype
    fsize <- input$fontsize
   
    if (! is.null(data_chemical()) )
    {
      para <- plotting_paras()
      act <- para[['act']]
      cv <- para[['cv']]
      dcols <- para[['dcols']]
      drows <- para[['drows']]
      annotation <- para[['annotation']]
      annt_colors <- para[['annt_colors']]
     
      if (showHeatmap)
      {
        if (profileType == 'signal_wauc')
        {
          pheatmap(t(act), fontsize=fsize,annotation=annotation,annotation_colors=annt_colors,breaks=breaks, color=color, clustering_distance_rows = drows, clustering_distance_cols = dcols, clustering_method = "average")
        } else
        {
          pheatmap_new_label(t(act), t(cv), fontsize=fsize,annotation=annotation,annotation_colors=annt_colors,breaks=breaks, color=color, display_numbers=TRUE, clustering_distance_rows = drows, clustering_distance_cols = dcols, clustering_method = "average")
        }
      } else
      {
        plot(hclust(dcols, method="average"), hang=-1)
      }
    }
  })

I can display the plot on web using renderPlot based on the reactive function (select_plot)

output$profiling <- renderPlot({
    select_plot()
 
  })

but somehow I can only download a blank png file.

output$downloadPlot <- downloadHandler(
    filename = function() { paste(input$proftype, '.png', sep='') },
    content = function(file) {
      png(file)
      select_plot()
      dev.off()
    }
  )


Thanks!

Patrick Renschler

unread,
Feb 26, 2014, 3:11:13 AM2/26/14
to shiny-...@googlegroups.com
Hi Jui-Hua Hsieh,

I've been having the same problem, but I've found a workaround.

Create a new function called select_plot2 that contains the same body as select_plot.

Instead of having it be reactive, structure it like this

select_plot2 = function() {

       ### INSERT CODE FROM select_plot

}

Then call select_plot2() from within your downloadHandler (instead of select_plot).

Like this:


output$downloadPlot <- downloadHandler(
    filename = function() { paste(input$proftype, '.png', sep='') },
    content = function(file) {
      png(file)
      #select_plot()
      select_plot2()
      dev.off()
    }
  )

None of the advice/solutions posted on this thread have worked for me, but this did. I'm not sure what the bug is with the reactive construct, but this seems to work.

tyler jacques

unread,
Aug 10, 2014, 2:40:45 PM8/10/14
to shiny-...@googlegroups.com
Just joined this group to say THANK YOU Patrick. I've been troubleshooting this issue for the last 4 hours and this work-around fixed it.

Much much appreciated.


Tyler

Barb Banbury

unread,
Aug 15, 2014, 2:14:58 PM8/15/14
to shiny-...@googlegroups.com
I have been having the same issue, and huge thanks to Patrick for giving a work around.  

I think ultimately, the issue is that plots are NULL objects.  If you type a <- plot(1:10, 2:11) into the console, a new plot window will appear but nothing will be stored in object "a".  For other plotting functions (like hist()), objects are created and stored, this workaround isn't needed because it creates an object that you can then download using plot(a). Typing b <- hist(rnorm(100)) into the console will both plot and store object "b" that can be plotted later.  Anyway, that is my understanding of the issue.  

Carlos Leite

unread,
Apr 26, 2016, 1:42:40 PM4/26/16
to Shiny - Web Framework for R, patrick....@gmail.com
I had the same problem. It is solved but I don't like to use a function. I would prefer a reactive one. What happens in a simple function? If I call it on renderPlot, for each reactive input changed, will the function run again? How does it behave that new select_plot2?
Reply all
Reply to author
Forward
0 new messages