2016-07-14 85 views
8

我使用Shiny和knitr的组合来创建PDF文档。通过Shiny将图片上传到knitr文档

目前我想添加功能,允许用户上传将被放置在创建的文件中的图片。然而,我真的被卡住了,因为我无法获得输入图片的路径。任何人都可以帮助我吗?

简单的例子:

应用:

library(knitr) 
library(shiny) 

ui <- fluidPage(

    sidebarLayout(
    sidebarPanel(
     fileInput("picture", label = 'Picture'), 
     downloadButton('report', label = 'Download PDF') 
    ), 

    mainPanel() 
) 
) 

server <- function(input,output){ 

    picture <- reactive({ 
    input$picture[,4] 
    }) 

    output$report = downloadHandler(
    filename = "test.pdf", 

    content = function(file){ 
     picture = picture() 

    out = knit2pdf(input = 'test.Rnw', compiler = 'xelatex', clean = TRUE) 
    file.rename(out, file) 
    }, 

    contentType = 'application/pdf' 
) 
} 

shinyApp(ui = ui, server = server) 

.Rnw文件:

\documentclass{article} 

\begin{document} 

Put picture here: 
<<echo = FALSE , message = F, results='asis'>>= 
cat(paste('\\includegraphics[height=3in]{', picture,'}')) 
@ 

\end{document} 

部分'\includegraphics[height=3in]{', picture,'}显然是造成问题的原因,因为我不知道图片路径只是暂时的一。

+1

上传的文件路径是'input $ picture $ datapath' –

+0

是的但它是临时目录的路径,我不知道如何使它工作。此外,$ datapath与我的代码中的[,4]相同。 –

+0

尝试在'.Rnw'文件中用'paste0'替换'paste',否则会在文件名后找不到尾部空格并且找不到图片。 – NicE

回答

2

你说你有光泽的服务器的工作,那么你应该不会介意的的完整路径图片,即使它在一个临时目录中(因为目前Shiny Server只能在Linux上运行,而LaTeX应该可以使用Linux文件路径,如/tmp/...../yourfile.png)。问题可能是datapath(即input$picture[, 4])没有文件扩展名,所以LaTeX无法识别它。您可以尝试检索原始文件的文件扩展名,并将上传的图片复制到具有相同扩展名的临时文件中,例如

picture <- reactive({ 
    path1 <- input$picture$datapath 
    path2 <- tempfile(fileext = gsub('^(.*)([.].+)$', '\\2', input$picture$name)) 
    file.copy(path1, path2, overwrite = TRUE) 
    path2 
}) 
+0

非常感谢您的回答,但我仍然可以运行我的错误上“test.tex”'运行“TEXI2DVI”失败 。 LaTeX的错误: LaTeX的错误:!文件“/ tmp目录/ RtmpoSS6qz/4683e6ec5bcf520337300eb1/0”不found.'我可能失去了一些东西很简单,但我真的无法弄清楚 –

+0

此外,我分配的活性功能'图片() '用'content = function(file){picture = pi简化'picture' cture()' –

+0

我明白了。对不起,我错过了。将在一分钟内更新答案。 –

1

我看到有两种方式解决:)

1的临时文件复制到您选择的文件夹,并使用该图片:如果你(在这种情况下,将R

observe({ 
     if (is.null(input$picture)) return() 
     picture<-"your/final/path/to/disk/uploadImage.jpg" # OR do a PASTE with the PATH and the upload file name 
     file.copy(input$picture$datapath, picture) 
     if(file.exists(picture)){ 
      # PROCESS THE IMAGE IF NEEDED 
     } 
     picture<<-picture # sometimes needed to R to see the variable outside the observe scope 
}) 

2)会话)不允许写入磁盘,您可以将该映像转换为base64变量并将其包含到Knitr文档中(或将其保存到数据库中作为字符串)。如果你愿意走这条弯路,这需要Knitr/HTML路线。 (从服务器运行的R工作室在读取/写入时几乎总是有很多限制,只能作为ADMIN进行处理,而服务器将会话视为RStudio而不是您,因此Rstudio必须具有所需的读/写权限您运行Shiny应用程序作为自动Rstudio Shiny会话,而不是使用RUN直接从RStudio运行)

确保base64可以通过Rouside'observe'或'if'作用域使用'< < - '连同'< - '。 R的范围很特别,所以一定要正确测试。

你应该潜入这个的(Base64)与网站,如:

https://github.com/yihui/knitr/issues/944

https://github.com/yihui/knitr/blob/master/R/utils-base64.R

+0

非常感谢您的回应。我将致力于实施,并让您知道您的方法是否允许我解决问题。正如你指出的,我实际上使用Shiny服务器,因此在写入权限方面存在问题。这就是为什么我使用提供的解决方案[这里](http://stackoverflow.com/questions/35800883/using-image-in-r-markdown-report-downloaded-from-shiny-app),但对于一些预定义的图像被放置在服务器上。我想知道当图像被用户上传时它是否可以应用于这种情况? –

+0

@经济学家,我会一直使用完整的系统路径(取决于系统从C:/ ....或/ .../...或ROOT开始,不希望在可以工作,但有些R程序员喜欢转移他们的工作目录(用setwd()和getwd()--- >>> not me though = ^)然后你就在盲人中......你可以,顺便说一句,总是在函数调用中获取临时文件目录:TEMPDIR() – irJvV