Search code examples
rshinyr-leaflet

Download leaflet map as a png when shiny app is deployed


I have a shiny app where users create maps and then can download them. Locally, this works, but when I have deployed it to shinyapps.io, the download feature no longer works and it indicates it is downloading an HTML document rather than a png.

The one thing I thought is that it could be around the need to run webshot::install_phantomjs(), which I have done locally, but it doesn't seem right/desirable to have this as a line in the app itself as then it will download stuff onto someone else's computer, take longer, and be inefficient if it keeps downloading every time.

This is a short example of the code I have to make/download a map:

library(shiny)
library(leaflet)
library(mapview)


ui<-       
  fluidPage(      
    leafletOutput("map_output"), 
    downloadButton("map_to_download")
  )

server <- function(input, output) {

  reactive_map <- reactive({
      leaflet()%>%
        addTiles()
  })

  output$map_output <-     renderLeaflet(
    reactive_map()
  )

  output$map_to_download <- downloadHandler(
    filename = "map.png",
    content = function(file) {
      mapshot(reactive_map(), file = file, 
              cliprect = "viewport", 
              selfcontained = FALSE)
    })
}

shinyApp(ui, server)

The above works on my machine (I have run webshot::install_phantomjs()), but the equivalent deployed does not download the map properly.

Does anybody know how to make this work when deployed on shinyapps.io, or have an alternative way of approaching downloading leaflet maps that would work?

EDIT: I've also tried this in the downloadHandler:

 output$map_to_download <- downloadHandler(
    filename = "map.png",
    content = function(file) {
      saveWidget(reactive_map(), "temp.html", selfcontained = FALSE)
      webshot::webshot("temp.html", file = file, cliprect = "viewport")
  })

This also works locally but not when deployed, although when deployed it downloads a text rather than HTML document.


Solution

  • My solution to this has been to add webshot::install_phantomjs() to my global file. I was considering this originally but was concerned about what it would do (as outlined in my post). However, adding it does not seem to create the adverse effects I was worried about, so adding this answer as an option for people facing the same problem.