How to make pdf download in shiny app response to user inputs?

耗尽温柔 提交于 2019-11-30 05:31:42

I apologize that it took me this long to get back to this. After looking at what I've done, it turns out it was a little more involved than I remembered.

Here's my example app code

library(shiny)
library(ggplot2)
library(magrittr)

ui <- shinyUI(
  fluidPage(
    column(
      width = 2,
      selectInput(
        inputId = "x_var",
        label = "Select the X-variable",
        choices = names(mtcars)
      ),
      selectInput(
        inputId = "y_var",
        label = "Select the Y-variable",
        choices = names(mtcars)
      ),
      selectInput(
        inputId = "plot_type",
        label = "Select the plot type",
        choices = c("scatter plot", "boxplot")
      ),
      downloadButton(
        outputId = "downloader",
        label = "Download PDF"
      )
    ),
    column(
      width = 3,
      tableOutput("table")
    ),
    column(
      width = 7,
      plotOutput("plot")
    )
  )
)

server <- shinyServer(function(input, output, session){

  #****************************************
  #* Reactive Values

  table <- reactive({
    mtcars[, c(input[["x_var"]], input[["y_var"]])]
  })

  plot <- reactive({
    p <- ggplot(data = mtcars,
                mapping = aes_string(x = input[["x_var"]],
                                     y = input[["y_var"]]))
    if (input[["plot_type"]] == "scatter plot")
    {
      p + geom_point()
    }
    else
    {
      p + geom_boxplot()
    }
  })

  #****************************************
  #* Output Components

  output$table <- 
    renderTable({
      table()
    })

  output$plot <- 
    renderPlot({
      plot()
    })

  #****************************************
  #* Download Handlers

  output$downloader <- 
    downloadHandler(
      "results_from_shiny.pdf",
      content = 
        function(file)
        {
          rmarkdown::render(
            input = "report_file.Rmd",
            output_file = "built_report.pdf",
            params = list(table = table(),
                          plot = plot())
          ) 
          readBin(con = "built_report.pdf", 
                  what = "raw",
                  n = file.info("built_report.pdf")[, "size"]) %>%
            writeBin(con = file)
        }
    )
})

shinyApp(ui, server)

And here is my RMD (entitled report_file.Rmd)

---
title: "Parameterized Report for Shiny"
output: pdf_document
params:
  table: 'NULL'
  plot: 'NULL'
---

```{r}
params[["plot"]]
```

```{r}
params[["table"]]
```

Some highlights to look for

  • Notice the exists of params in the YAML front matter of the RMarkdown script. This allows us to pass in a list of values to be used in the script when we invoke rmarkdown::render(..., params = list(...))
  • I always build my PDF to a dummy file. That way it's easy to find.
  • The reason I always build to a dummy file is that to get the download handler to work, you need to read the bit-content of the PDF and push it to the file argument using writeBin. See my downloadHandler construction.
  • Using the parameterized report means you don't have to recreate your outputs in the rmarkdown script. The work was done in the Shiny app, the parameterized report just helps you send the objects correctly. It isn't quite the same as passing files back and forth (although if it could be that easy, I'd love to know it).

Read more about parameterized reports here: http://rmarkdown.rstudio.com/developer_parameterized_reports.html

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!