2

When running the following shiny app from the console with runApp(), it works as expected, displaying a plot and providing the ability to download an excel file with the plot embedded. Running the same app on shiny-server, yields the error

cannot open file 'Rplots.pdf'

  • Shiny Server v1.4.2.786
  • Node.js v0.10.40
  • R version 3.3.1 (2016-06-21) -- "Bug in Your Hair"
  • Ubuntu 14.04.4 LTS

    library(shiny)
    library(openxlsx)
    library(magrittr)
    
    # Define UI for application that draws a histogram
    ui <- shinyUI(fluidPage(
    
       # Application title
       titlePanel("Old Faithful Geyser Data"),
    
       # Sidebar with a slider input for number of bins 
       sidebarLayout(
          sidebarPanel(
             sliderInput("bins",
                         "Number of bins:",
                         min = 1,
                         max = 50,
                         value = 30),
             downloadButton('specDataDownload',
                            label = "Download",
                            class = NULL)
          ),
    
          # Show a plot of the generated distribution
          mainPanel(
             plotOutput("distPlot")
          )
       )
    ))
    
    # Define server logic required to draw a histogram
    server <- shinyServer(function(input, output) {
    
       output$distPlot <- renderPlot({
          # generate bins based on input$bins from ui.R
          x    <- isolate({faithful[, 2] })
          bins <- seq(min(x), max(x), length.out = input$bins + 1)
    
          # draw the histogram with the specified number of bins
          hist(x, breaks = bins, col = 'darkgray', border = 'white')
    
       })
       output$specDataDownload <- downloadHandler(
           filename = function() {
               paste("ProcessedPlateAssay",
                     gsub("-|[[:space:]]|:",
                          "",
                          Sys.time()),
                     ".xlsx",
                     sep = "_")
           },
           content = function(con) {
               x    <- isolate({faithful[, 2] })
               bins <- seq(min(x), max(x), length.out = input$bins + 1)
               output <- createWorkbook()
               addWorksheet(
                   output,
                   "One")
               hist(
                   x,
                   breaks = bins,
                   col = 'darkgray',
                   border = 'white')
               insertPlot(
                   output,
                   sheet = 1,
                   startRow = (1),
                   startCol = 5,
                   width = 6.5,
                   height = 3,
                   fileType = "png",
                   units = "in",
                   dpi = 600)
    
           saveWorkbook(
               wb = output,
               file = con
           )
           })
    })
    
    # Run the application 
    shinyApp(ui = ui, server = server)
    
bwbioinfo
  • 81
  • 8
  • Ran into the same issue. Here's how we solved it: (1) use jpeg to open a (temporary) plot; (2) execute your plot command, (3) close the jpeg, use insertImage. – PMaier Jul 21 '16 at 17:48
  • Hi, I ultimately solved that aspect as well but the underlying issue was that the shiny user on my server didn't have write permission to the folder (it was created as a git repository and pushed to the server). – bwbioinfo Aug 26 '16 at 15:18

1 Answers1

3

I thought to provide a minimal example since I have struggled with the issue of openxlsx's insertPlot function not working inside shiny-server, probably due to permission issues with tempfile or dev.copy. The method that worked best for me was to use ggsave, since it handles resolution very neatly, and also has a scale parameter which allows resizing of the image elements making it more suitable for a presentation. I have also included a second method using the png function.

Below is a reproducible example, partly drawn from the answer by @sebkopf in Save plots made in a shiny app

library(shiny)
library(openxlsx)
library(ggplot2)

ui <- fluidPage(
  downloadLink("downloadExcel", "Excel Graph Download")
)

server <- function(input, output) {

  p1 <- qplot(mpg, data=mtcars, geom="density", fill=as.factor(gear), 
alpha=I(.5), main="Distribution of Gas Mileage")
  p2 <- qplot(age, circumference, data = Orange, geom = c("point", "line"), 
colour = Tree)

  output$downloadExcel <- downloadHandler(
    filename = "savePlot.xlsx",
    content = function(file){
      wb <- createWorkbook()

      addWorksheet(wb, "ggsave", gridLines = F)
      addWorksheet(wb, "png", gridLines = F)

      # Method 1: using ggsave

      ggsave("p1.png", plot = p1, scale = .6) # Scale parameter resizes the object making text more legible
      ggsave("p2.png", plot = p2, scale = .6)

      insertImage(wb, "ggsave", "p1.png", width = 5, height = 3.5)
      insertImage(wb, "ggsave", "p22.png", startCol = "J", width = 16, height = 10, units = "cm")

      # Method 2: using png function

      png("p11.png")
      print(p1)
      dev.off()

      insertImage(wb, "png", "p11.png", width = 5, height = 3.5)

      png("p22.png")
      print(p2)
      dev.off()

      insertImage(wb, "png", "p22.png", startCol = "J", width = 16, height = 10, units = "cm")

      saveWorkbook(wb, file, overwrite = T)

      unlink(c("p1", "p2", "p11", "p22")) # To remove the images from the server
    }
  )
}

shinyApp(ui, server)
Joseph Kigotho
  • 179
  • 1
  • 14
  • And remember to check if shiny is the owner of the directory you are trying to write into: https://groups.google.com/forum/#!topic/shiny-discuss/srWETT6uL-I through `sudo chown shiny:shiny /var/shiny-server/www/shiny_test/work` – Joseph Kigotho Nov 16 '18 at 15:28