2016-07-14 60 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

相關問題