Search code examples
rshinyr-markdownlan

Generating downloadable reports with shiny in LAN


I shared an Rshiny app in LAN with my coworkers PCs, so I used shiny.host and shiny.port

So when my coworkers in theirs PCs tried to download reports when clicking in a report_button button, they received the last values that I chose on my PC

example: On my PC I choose input$slider = 46 and I download the report file in HTML, then my coworker on his PC opens the link 192.168.5.140:8888 in his browser, chooses input$slider=73 and downloads the file, and then (!!!) he gets the same report that I got, i.e he gets input$slider = 46

here is the code :

library(shiny)
options(shiny.host = '192.168.5.140')
options(shiny.port = 8888)

ui = fluidPage(
  sliderInput("slider", "Slider", 1, 100, 50),
  downloadButton("report_button", "Generate report") 
)

server = function(input, output) {

  output$report_button<- downloadHandler(
        # For PDF output, change this to "report.pdf"
     filename = "report.html",
     content = function(file) {
        # Copy the report file to a temporary directory before processing it, in
        # case we don't have write permissions to the current working dir (which
        # can happen when deployed).
     tempReport <- file.path(tempdir(), "report.Rmd")
     file.copy("report.Rmd", tempReport, overwrite = TRUE)
    
        # Set up parameters to pass to Rmd document
     params <- list(n = input$slider)
    
        # Knit the document, passing in the `params` list, and eval it in a
        # child of the global environment (this isolates the code in the document
        # from the code in this app).
     rmarkdown::render(tempReport, output_file = file,
                      params = params,
                      envir = new.env(parent = globalenv())
         )
       }
     )
    }
shinyApp(ui, server)

and the report.RMD file :

---
title: "Dynamic report"
output: html_document
params:
  n: NA
---

```{r}
 # The `params` object is available in the document.
params$n
```

Solution

  • You should be able to prevent this situation by using tempfile instead of tempdir to create the temporary Rmd file.

    tempdir is constant as long as you are running the same R-session - which might end up in concurrent shiny sessions overwriting each others report results.

    tempfile however, creates a unique file for each function call:

    library(shiny)
    options(shiny.host = '0.0.0.0')
    options(shiny.port = 8888)
    
    ui = fluidPage(
      sliderInput("slider", "Slider", 1, 100, 50),
      downloadButton("report_button", "Generate report") 
    )
    
    server = function(input, output) {
      
      output$report_button<- downloadHandler(
        # For PDF output, change this to "report.pdf"
        filename = "report.html",
        content = function(file) {
          # Copy the report file to a temporary directory before processing it, in
          # case we don't have write permissions to the current working dir (which
          # can happen when deployed).
          tempReport <- tempfile(fileext = ".Rmd")
          file.copy("report.Rmd", tempReport, overwrite = TRUE)
          
          # Set up parameters to pass to Rmd document
          params <- list(n = input$slider)
          
          # Knit the document, passing in the `params` list, and eval it in a
          # child of the global environment (this isolates the code in the document
          # from the code in this app).
          rmarkdown::render(tempReport, output_file = file,
                            params = params,
                            envir = new.env(parent = globalenv())
          )
        }
      )
    }
    shinyApp(ui, server)