Loading an image into a knitr document via Shiny

I use a combination of Shiny and knitr to create PDF documents.

Currently, I want to add a function that will allow the user to upload an image that will be placed in the created document. However, I am really stuck because I cannot get the path to the input picture. Can someone help me with this?

A simple example:

Application:

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) 

and .Rnw :

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

The '\includegraphics[height=3in]{', picture,'} obviously causes a problem because I don't know that the image path is only temporary.

+8
r shiny knitr
source share
2 answers

You said that you are working with Shiny Server, then you should be fine with the full path of the image, even if it is in the temporary directory (since currently Shiny Server only works with Linux, and LaTeX should be fine with Linux file path e.g. /tmp/...../yourfile.png ). Perhaps the problem is that datapath (ie, input$picture[, 4] ) does not have a file extension, so LaTeX could not recognize it. You can try to restore the file extension of the source file and copy the downloaded image to a temporary file with the same extension, for example.

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

I see the solution in two ways:

1) copy the temporary file to the folder of your choice and use this image:

 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) if you (in this case the R session) are not allowed to write to disk, you can turn the image into a base64 variable and include it in your Knitr document (or save it in the database as a string). This will take the Knitr / HTML route if you are ready to take this detour. (An R-studio working with a server almost always has a lot of read / write restrictions, which you can only process as ADMIN. And the server performs a brilliant session like RStudio, not you, so Rstudio should have the read / write permissions necessary if you start the Shiny app as an automatic Rstudio Shiny session and don't start it directly from RStudio using RUN)

Make sure that base64 is read using the R ouside "watch" or "if" area again, using "<<-" along with "<-". Scoring is something special with R, so be sure to check it correctly.

You should dive into this (base64) with sites such as:

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

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

+1
source share

All Articles