Search code examples
shinydownloadzip

R shiny download zipped shp file


I try to develop a shiny app where a sf object is created and can be downloaded as a shp file in a zip folder. Preferably the shp geometry is packed in a subfolder:

-myzip |-mygeometry |--myshape.shp

I tried modifications (tar and zip) of the following code but never succeeded.

library(shiny)
library(sf)

##sf object
data <- data.frame(
  x = c(1, 2, 3),
  y = c(4, 5, 6)
)
colnames(data) <- c("x", "y")

# Converting to sf object
sf_object <- st_as_sf(data, coords = c("x", "y"))


ui <- fluidPage(
  titlePanel("Download zip"),
  
  mainPanel(
                   downloadButton("downloadData", label = "Download")
      
  )
)

server<-function(input,output,session){
  output$downloadData <- downloadHandler(
    filename = function() {
      paste("myzip", "zip", sep = ".")
    },
    content = function(fname) {
      fs <- c()
      tmpdir <- tempdir()
      setwd(tempdir())
      path <- paste0(tmpdir,"/mysf_object",".shp")
      fs <- c(sf_object, path)
      st_write(sf_object,path)
      zipr(zipfile = fname, files = fs)
    },
    contentType = "application/zip"
  )
  
}

# Run the application
shinyApp(ui = ui, server = server)

Solution

  • Try this. One of the problems with your version is that you didn't create the directory and also st_write creates four files, but you were only including one of them in the call to zip::zipr

     output$downloadData <- downloadHandler(
        filename = function() {
          "myzip.zip"
        },
        content = function(fname) {
          tmpdir <- tempdir()
          setwd(tempdir())
          directory <- file.path(tmpdir, "mygeometry")
          dir.create(directory)
          path <- file.path(directory, "mysf_object.shp")
          st_write(sf_object, path)
    
          files <- file.path("mygeometry", list.files("mygeometry/"))
          
          zip::zipr(zipfile = fname,
               files = files,
               include_directories = TRUE,
               mode = "mirror")
        }
      )