Q:

displaying a pdf from a local drive in shiny

I'm still new to r and shiny, and i'm stumped with what should otherwise be simple logic. I am trying to display pdf files in imageOutput widgets but with no luck. Could someone steer me in the right direction?
sample ui.R
shinyUI(pageWithSidebar(
mainPanel(
  selectInput("sel_ed",
              label = "View outputs for Ecodistrict:", 
              choices = c(244,245,247,249), 
              selected = NULL,
              multiple = FALSE),

  imageOutput("imp_pdf",width="500px",height="500px")
))

sample server.R
shinyServer(function(input, output, session) {

importance <- function(inputSpecies){
img_dir <- pdf(paste(inputSpecies,"\\models\\MATL\\MATRF_Importance",sep=""))
}

output$imp_pdf <- renderImage({importance(input$sel_ed)}) 

})

Most of the errors i get have to do with expected character vector arguments, or atomic vectors. I know that shiny is more or less designed to render AND display images or plots but there has to be a way to display pdf's that are already on a local drive..

A:

To embed a PDF viewer (the default PDF viewer of your web browser, pdf.js on mozilla for example) in your Shiny ui, you can use an iframe which the src will be the path to your PDF.
Here is 2 differents ways to include an iframe in your interface :
in the Ui you can directly add an iframe tag with an absolute src attribute as bellow :
tags$iframe(style="height:600px; width:100%", src="http://localhost/ressources/pdf/R-Intro.pdf"))

Or get an URL from the ui in the server , write the iframe tag with the input URL and return the HTML code in a htmlOutput in the ui :
Ui :
textInput("pdfurl", "PDF URL")
htmlOutput('pdfviewer')
Server :  
output$pdfviewer <- renderText({
    return(paste('<iframe style="height:600px; width:100%" src="', input$pdfurl, '"></iframe>', sep = ""))
})

Note that when pages are loaded with a HTTP(S) protocol (the case of the Shiny app) for security reasons you can't framed locals files with their "file:" URLs. If you want to display locals pdf you should access to them with a http(s): URL, so you have to save them in your www directory (a local web server) and access to files with their http(s): URLs (the URL will be something like http://localhost/.../mypdf.pdf) as in the second iframe of my example. (Then you can't use a fileInput directly, you have to format it)
Ui.R :
library(shiny)

row <- function(...) {
  tags$div(class="row", ...)
}

col <- function(width, ...) {
  tags$div(class=paste0("span", width), ...)
}

shinyUI(bootstrapPage(

  headerPanel("PDF VIEWER"),

  mainPanel(

    tags$div(
      class = "container",

      row(
        col(3, textInput("pdfurl", "PDF URL"))
      ),
      row(
        col(6, htmlOutput('pdfviewer')),
        col(6, tags$iframe(style="height:600px; width:100%", src="http://localhost/ressources/pdf/R-Intro.pdf"))
      )
    )
  )
))

Server.R :
shinyServer(function(input, output, session) {

  output$pdfviewer <- renderText({
      return(paste('<iframe style="height:600px; width:100%" src="', input$pdfurl, '"></iframe>', sep = ""))
  })

})

The web pages with the PDF viewers :

Hope this help.

A:

Create a folder called www in the original directory that contains your server.R and ui.R scripts.  Place the PDF in the www/ folder, then use something like the code below:
In server.R:
shinyServer(function(input, output) {

  observeEvent(input$generate, {
    output$pdfview <- renderUI({
      tags$iframe(style="height:600px; width:100%", src="foo.pdf")
    })
  })
})

In ui.R:
shinyUI(fluidPage(

  titlePanel("Display a PDF"),

  sidebarLayout(
    sidebarPanel(
      actionButton("generate", "Generate PDF")
    ),

    mainPanel(
      uiOutput("pdfview")
    )
  )
))

