R Shiny/R Markdown: render() fails inside downloadHandler

1.9k Views Asked by At

I have an RMarkdown template, template.Rmd:

---
title: "Template"
output: tufte_handout
params:
    data: !r data.frame()
---

```{r setup, include=FALSE}
library(ggplot2)
knitr::opts_chunk$set(echo = TRUE)
```

# Title

## Another Title

```{r echo=FALSE}
ggplot(data = params$data, mapping = aes(x=params$data$X, y=params$data$Y)) +
  geom_point()
```

Then I have this R Shiny app, app.R:

library(shiny)
library(rmarkdown)

data <- data.frame(X = 1:10, Y = 11:20)

ui <- fluidPage(fluidRow(column(
  width = 6,
  actionButton("actionButton", "PDF"),
  downloadButton("downloadButton", "PDF")
)))

server <- function(input, output) {
  observeEvent(input$actionButton, {
    renderedFile <- render(
      input = "template.Rmd",
      output_format = "tufte::tufte_handout",
      params = list(data = data),
      output_file = "output.pdf"
    )
    browseURL(renderedFile)


  })
  output$downloadButton <-
    downloadHandler(filename <- "output.pdf",
                    content <-
                      function(file) {
                        renderedFile <- render(
                          input = "template.Rmd",
                          output_format = "tufte::tufte_handout",
                          params = list(data = data),
                          output_file = "output.pdf"
                        )
                        file.copy(renderedFile, file)
                      })
}

shinyApp(ui = ui, server = server)

There's one actionButton and one downloadButton. They both are supposed to do the same, more or less: render a PDF (a Tufte handout, to be precise), and open respectively download it. While browseURL works great when I run the example on my machine, I need the downloadHandler when running the app in a "real" server.

The actionButton works perfectly, but the downloadButton fails:

"C:/PROGRA~2/Pandoc/pandoc" +RTS -K512m -RTS template.utf8.md --to latex --from markdown+autolink_bare_uris+ascii_identifiers+tex_math_single_backslash --output pandoc7146d9cfc5.pdf --template "C:\Users\paedubucher\Documents\R\win-library\3.4\tufte\rmarkdown\templates\tufte_handout\resources\tufte-handout.tex" --highlight-style pygments --latex-engine pdflatex --variable "documentclass:tufte-handout" 
! Undefined control sequence.
<argument> C:\temp 
                   \RtmpAtAlbM \file 714614f62c3_files
l.78 ...62c3_files/figure-latex/unnamed-chunk-1-1}

pandoc.exe: Error producing PDF
Warning: running command '"C:/PROGRA~2/Pandoc/pandoc" +RTS -K512m -RTS template.utf8.md --to latex --from markdown+autolink_bare_uris+ascii_identifiers+tex_math_single_backslash --output pandoc7146d9cfc5.pdf --template "C:\Users\paedubucher\Documents\R\win-library\3.4\tufte\rmarkdown\templates\tufte_handout\resources\tufte-handout.tex" --highlight-style pygments --latex-engine pdflatex --variable "documentclass:tufte-handout"' had status 43
Warning: Error in : pandoc document conversion failed with error 43
Stack trace (innermost first):
    53: pandoc_convert
    52: convert
    51: render
    50: download$func [C:\Users\paedubucher\Documents\R\pdf-download/app.R#28]
     1: runApp
Error : pandoc document conversion failed with error 43

EDIT: Now there's the proper error message. Pandoc fails (Error 43), but everything works fine when it is run inside the actionButton context.

1

There are 1 best solutions below

0
On BEST ANSWER

The friendly R Shiny folks on GitHub pointed out the problem. output_file is not supposed to be used in that way. It's just the intermediate LaTeX file. The location of the PDF file is returned from render. This file just needs to be moved to the place the file parameter is pointing to:

  output$downloadButton <-
    downloadHandler(
      filename = "output.pdf",
      content =
        function(file) {
          output <- render(
            input = "template.Rmd",
            output_format = "tufte::tufte_handout",
            params = list(data = data)
          )
          file.copy(output, file)
        }
    )