J Louro
J Louro

Reputation: 43

Error with downloadHandler downloading an image with R Shiny

I've spent the last days trying to add a button to download an image in my shiny application and I can't get it. I've done it before with other applications, but this one doesn't work. The application chooses two images (or three) and merges them with the transparency you want. The image in the app looks perfect, the problem is only with the download. The server code is as follows;

library(shiny)
library(abind)
library(jpeg)
library(rsconnect)

shinyServer(function(input, output) {

  
output$myImage <- renderImage({
  # A temp file to save the output.

  # Return a list containing the filename and alt text

  
  
  outfile <- tempfile(fileext = '.png')
  
  image1 = jpeg::readJPEG(file.path(
                                    paste(input$map1,'.jpeg', sep='')))
  
  image2 = jpeg::readJPEG(file.path(
                                              paste(input$map2,'.jpeg', sep='')))
  
  image3 = jpeg::readJPEG(file.path(
    paste(input$map3,'.jpeg', sep='')))


  
  image1 = abind::abind(image1, image1[,,1]) # add an alpha channel
  image1[,,4] = input$trans1 # set alpha to semi-transparent
  
  image2 = abind::abind(image2, image2[,,1]) # add an alpha channel
  image2[,,4] = input$trans2

  image3 = abind::abind(image3, image3[,,1]) # add an alpha channel
  image3[,,4] = input$trans3
  
  if(input$n==0){
    png(outfile, width = 4, height = 4, units = 'in', res = 300)
    par(mai=c(0,0,0,0))
    plot.new()
    rasterImage(image1, 0, 0, 1, 1)
    rasterImage(image2, 0, 0, 1, 1)
    dev.off()
  }
  
  if(input$n==1){
    png(outfile, width = 2, height = 2, units = 'in', res = 300)
    par(mai=c(0,0,0,0))
    plot.new()
    rasterImage(image1, 0, 0, 1, 1)
    rasterImage(image2, 0, 0, 1, 1)
    
    rasterImage(image3, 0, 0, 1, 1)
    dev.off()
  }
  
  
  
  # Return a list containing the filename
  list(src = outfile,
       contentType = 'image/png',
       width = 600,
       height = 400,
       alt = "This is alternate text")
  
  
}, deleteFile = FALSE)


output$downloadImage <- downloadHandler(
  filename = "Image.png",
  contentType = "image/png",
  content = function(file) {
    ## copy the file from the updated image location to the final download location
    file.copy(outfile, file)
  }
)  


}

The ui code is the following:

library(abind)
library(shiny)
library(rsconnect)
library(jpeg)
library(shiny)
library(shinyBS)
library(shinyjs)

shinyUI(fluidPage(

  
  tags$head(tags$style(
    HTML('
         #sidebar {
     float: right;

         background-color: white;
         border-bottom: 1px solid #e6e6e6;
         border-radius: 0;
         
         }
         
         body, label, input, button, select { 
     font-family: "Open Sans", Arial, sans-serif;
         }')
  )),
  
  sidebarLayout(position = "right",
    sidebarPanel(
   
    
      
      selectInput(inputId = "map1",
                  label = "Mapa 1:",
                  choices = c("Mapa 1","Mapa 2","Mapa 3","Mapa 4","Mapa 5"),
                  selected = "Normal"),
    
      
      sliderInput(inputId = "trans1",
                 label = "Transparencia mapa 1:",
                 min = 0, max = 1, value = 0.5, step = 0.1),
      
   selectInput(inputId = "map2",label = "Mapa 2:",
                                                                 choices = c("Mapa 1","Mapa 2","Mapa 3","Mapa 4","Mapa 5"),
                                                                 selected = "Normal"),
      
      
      sliderInput(inputId = "trans2",label = "Transparencia mapa 2:",
                                                                 min = 0, max = 1, value = 0.5, step = 0.1),  
    

      hr(),
   
  checkboxInput( "n", "Anadir otro mapa:",FALSE), 
  
  hr(),
   
   
            conditionalPanel(condition = "input.n==1", selectInput(inputId = "map3",label = "Mapa 3:",
                         choices = c("Mapa 1","Mapa 2","Mapa 3","Mapa 4","Mapa 5"),
                         selected = "Normal")),
             
             
  conditionalPanel(condition = "input.n==1", sliderInput(inputId = "trans3",label = "Transparencia mapa 3:",
                         min = 0, max = 1, value = 0.5, step = 0.1)
   )
   ,
      hr()
      ,
  downloadButton('downloadImage', 'Download modified image'),
  
  hr()
    ),
    mainPanel(
      imageOutput("myImage")
  )
)))

The first thing when I push download, instead of trying to download "Image.png" it says to download the file "downloadImage" without extension. Then if i accept it gives the following error:

Error

Anyobdy knows which is the error? I'm desperated!

Thanks

Upvotes: 1

Views: 570

Answers (1)

St&#233;phane Laurent
St&#233;phane Laurent

Reputation: 84519

outfile is defined inside the renderImage, and then it does not exist in the downloadHandler. So define it at the root of your server function:

shinyServer(function(input, output) {

  outfile <- tempfile(fileext = '.png')
  
  output$myImage <- renderImage({
    ......

Upvotes: 3

Related Questions