在闪亮的应用程序中,downloadHandler() 无法从 rmarkdown::render() 呈现 pdf 是有原因的吗?
In a shiny app is there a reason downloadHandler() can't render a pdf from rmarkdown::render()?
我有一个复杂的闪亮应用程序,它运行完美,除了一个下载按钮,该按钮旨在从 rmarkdown 呈现 pdf 以生成可下载的报告。
简而言之 shell downloadHandler() 没有成功地从 rmarkdown::render() 渲染 pdf,但是 Rstudio 从 .Rmd 文件编织 pdf 很好,并且 Rstudio 可以编译 pdf临时文件中的 .tex 文件没有问题。
简化代码:
我的 shiny 应用程序使用多文件布局,这个最小的代码在我的机器上重现了问题,比我的实际 shiny 应用程序复杂得多。
重现错误的简单代码
ui.R
#
# This is the user-interface definition of a Shiny web application. You can
# run the application by clicking 'Run App' above.
#
# Find out more about building applications with Shiny here:
#
# http://shiny.rstudio.com/
#
library(shiny)
# Define UI for application that draws a histogram
shinyUI(fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30),
downloadButton("Markdown", "Generate report")
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
))
server.R
#
# This is the server logic of a Shiny web application. You can run the
# application by clicking 'Run App' above.
#
# Find out more about building applications with Shiny here:
#
# http://shiny.rstudio.com/
#
library(shiny)
# Define server logic required to draw a histogram
shinyServer(function(input, output) {
output$distPlot <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
#options(tinytex.verbose = TRUE)
##---- Markdown ----
source('06_Save_pdf_report.R', local = TRUE)
})
06_Save_pdf_report.R
output$Markdown <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "report.pdf",
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(), "07_tester.Rmd")
file.copy("07_tester.Rmd", tempReport, overwrite = TRUE)
# 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_format = "pdf_document",
output_file = file
)
}
)
07_tester.Rmd
---
title: "07_tester.Rmd"
author: "CB"
date: "2/10/2021"
output: pdf_document
---
```{r setup, include=FALSE}
options(tinytex.verbose = TRUE)
knitr::opts_chunk$set(echo = FALSE)
```
## R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.
When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
```{r cars}
summary(cars)
```
## Including Plots
You can also testingwithout plots, for example:
```{r pressure, echo=FALSE}
summary(cars)
```
Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.
确定问题和错误
如果我编织 07_tester.Rmd 文件,我得到一个 pdf 没问题。当我 运行 闪亮的应用程序并单击“生成报告”按钮时,我在控制台中看到正常的 rmarkdown activity,最后会弹出一个 window 用于保存文件的位置,注意它不包含 06_Save_pdf_report.R 代码中的文件名。单击保存按钮后,控制台中出现以下错误:
Warning: Error in : LaTeX failed to compile C:\Users\USER\AppData\Local\Temp\RtmpQD0jkj\file49b85d6276e8.tex. See https://yihui.org/tinytex/r/#debugging for debugging tips.
[No stack trace available]
在此之前没有警告或错误,应用程序继续 运行 之后没有问题。没有文件实际保存或下载到任何地方。
如果我转到 C:\Users\USER\AppData\Local\Temp\RtmpQD0jkj\ 并在 Rstudio 中打开 file49b85d6276e8.tex 文件,我可以将它编译为 pdf 而不会出错。从闪亮的应用程序尝试中,临时文件夹还包含一个 texput.log 文件,它显示:
This is pdfTeX, Version 3.14159265-2.6-1.40.21 (TeX Live 2020/W32TeX) (preloaded format=pdflatex 2021.2.10) 10 FEB 2021 18:04
entering extended mode
restricted \write18 enabled.
%&-line parsing enabled.
**C:/Users/USER/AppData/Local/Temp/RtmpQD0jkj/file49b85d6276e8.tex
! Emergency stop.
<to be read again>
\protect
<*> C:/Users/USER
/AppData/Local/Temp/RtmpQD0jkj/file49b85d6276e8.tex
Here is how much of TeX's memory you used:
4 strings out of 481250
115 string characters out of 5913850
266128 words of memory out of 5000000
17047 multiletter control sequences out of 15000+600000
403430 words of font info for 27 fonts, out of 8000000 for 9000
14 hyphenation exceptions out of 8191
3i,0n,0p,1b,6s stack positions out of 5000i,500n,10000p,200000b,80000s
! ==> Fatal error occurred, no output PDF file produced!
我在网上到处搜索,没有找到任何有用的信息。我一定是犯了一些简单的错误,如果能指出正确的方向,我们将不胜感激。
正如@RemkoDuursma 在评论中指出的那样 :
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:
library(rmarkdown)
library(tinytex)
library(shiny)
shinyApp(
#
# This is the user-interface definition of a Shiny web application. You can
# run the application by clicking 'Run App' above.
#
# Find out more about building applications with Shiny here:
#
# http://shiny.rstudio.com/
#
# Define UI for application that draws a histogram
ui = shinyUI(fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30),
downloadButton("Markdown", "Generate report")
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
)),
server = function(input, output) {
#
# This is the server logic of a Shiny web application. You can run the
# application by clicking 'Run App' above.
#
# Find out more about building applications with Shiny here:
#
# http://shiny.rstudio.com/
#
# Define server logic required to draw a histogram
output$distPlot <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
#options(tinytex.verbose = TRUE)
##---- Markdown ----
output$Markdown <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "report.pdf",
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(), "07_tester.Rmd")
file.copy("07_tester.Rmd", tempReport, overwrite = TRUE)
# 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).
output <- rmarkdown::render(
input = tempReport
)
file.copy(output, file)
})
}
)
注意 我也在这里回答因为我也遇到了同样的问题,先到这里,错过了欺骗评论了一会儿。希望这可以节省一些时间。
我有一个复杂的闪亮应用程序,它运行完美,除了一个下载按钮,该按钮旨在从 rmarkdown 呈现 pdf 以生成可下载的报告。
简而言之 shell downloadHandler() 没有成功地从 rmarkdown::render() 渲染 pdf,但是 Rstudio 从 .Rmd 文件编织 pdf 很好,并且 Rstudio 可以编译 pdf临时文件中的 .tex 文件没有问题。
简化代码:
我的 shiny 应用程序使用多文件布局,这个最小的代码在我的机器上重现了问题,比我的实际 shiny 应用程序复杂得多。
重现错误的简单代码
ui.R
#
# This is the user-interface definition of a Shiny web application. You can
# run the application by clicking 'Run App' above.
#
# Find out more about building applications with Shiny here:
#
# http://shiny.rstudio.com/
#
library(shiny)
# Define UI for application that draws a histogram
shinyUI(fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30),
downloadButton("Markdown", "Generate report")
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
))
server.R
#
# This is the server logic of a Shiny web application. You can run the
# application by clicking 'Run App' above.
#
# Find out more about building applications with Shiny here:
#
# http://shiny.rstudio.com/
#
library(shiny)
# Define server logic required to draw a histogram
shinyServer(function(input, output) {
output$distPlot <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
#options(tinytex.verbose = TRUE)
##---- Markdown ----
source('06_Save_pdf_report.R', local = TRUE)
})
06_Save_pdf_report.R
output$Markdown <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "report.pdf",
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(), "07_tester.Rmd")
file.copy("07_tester.Rmd", tempReport, overwrite = TRUE)
# 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_format = "pdf_document",
output_file = file
)
}
)
07_tester.Rmd
---
title: "07_tester.Rmd"
author: "CB"
date: "2/10/2021"
output: pdf_document
---
```{r setup, include=FALSE}
options(tinytex.verbose = TRUE)
knitr::opts_chunk$set(echo = FALSE)
```
## R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.
When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
```{r cars}
summary(cars)
```
## Including Plots
You can also testingwithout plots, for example:
```{r pressure, echo=FALSE}
summary(cars)
```
Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.
确定问题和错误
如果我编织 07_tester.Rmd 文件,我得到一个 pdf 没问题。当我 运行 闪亮的应用程序并单击“生成报告”按钮时,我在控制台中看到正常的 rmarkdown activity,最后会弹出一个 window 用于保存文件的位置,注意它不包含 06_Save_pdf_report.R 代码中的文件名。单击保存按钮后,控制台中出现以下错误:
Warning: Error in : LaTeX failed to compile C:\Users\USER\AppData\Local\Temp\RtmpQD0jkj\file49b85d6276e8.tex. See https://yihui.org/tinytex/r/#debugging for debugging tips.
[No stack trace available]
在此之前没有警告或错误,应用程序继续 运行 之后没有问题。没有文件实际保存或下载到任何地方。
如果我转到 C:\Users\USER\AppData\Local\Temp\RtmpQD0jkj\ 并在 Rstudio 中打开 file49b85d6276e8.tex 文件,我可以将它编译为 pdf 而不会出错。从闪亮的应用程序尝试中,临时文件夹还包含一个 texput.log 文件,它显示:
This is pdfTeX, Version 3.14159265-2.6-1.40.21 (TeX Live 2020/W32TeX) (preloaded format=pdflatex 2021.2.10) 10 FEB 2021 18:04
entering extended mode
restricted \write18 enabled.
%&-line parsing enabled.
**C:/Users/USER/AppData/Local/Temp/RtmpQD0jkj/file49b85d6276e8.tex
! Emergency stop.
<to be read again>
\protect
<*> C:/Users/USER
/AppData/Local/Temp/RtmpQD0jkj/file49b85d6276e8.tex
Here is how much of TeX's memory you used:
4 strings out of 481250
115 string characters out of 5913850
266128 words of memory out of 5000000
17047 multiletter control sequences out of 15000+600000
403430 words of font info for 27 fonts, out of 8000000 for 9000
14 hyphenation exceptions out of 8191
3i,0n,0p,1b,6s stack positions out of 5000i,500n,10000p,200000b,80000s
! ==> Fatal error occurred, no output PDF file produced!
我在网上到处搜索,没有找到任何有用的信息。我一定是犯了一些简单的错误,如果能指出正确的方向,我们将不胜感激。
正如@RemkoDuursma 在评论中指出的那样
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:
library(rmarkdown)
library(tinytex)
library(shiny)
shinyApp(
#
# This is the user-interface definition of a Shiny web application. You can
# run the application by clicking 'Run App' above.
#
# Find out more about building applications with Shiny here:
#
# http://shiny.rstudio.com/
#
# Define UI for application that draws a histogram
ui = shinyUI(fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30),
downloadButton("Markdown", "Generate report")
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
)),
server = function(input, output) {
#
# This is the server logic of a Shiny web application. You can run the
# application by clicking 'Run App' above.
#
# Find out more about building applications with Shiny here:
#
# http://shiny.rstudio.com/
#
# Define server logic required to draw a histogram
output$distPlot <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
#options(tinytex.verbose = TRUE)
##---- Markdown ----
output$Markdown <- downloadHandler(
# For PDF output, change this to "report.pdf"
filename = "report.pdf",
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(), "07_tester.Rmd")
file.copy("07_tester.Rmd", tempReport, overwrite = TRUE)
# 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).
output <- rmarkdown::render(
input = tempReport
)
file.copy(output, file)
})
}
)
注意 我也在这里回答因为我也遇到了同样的问题,先到这里,错过了欺骗评论了一会儿。希望这可以节省一些时间。