moman822
moman822

Reputation: 1954

Download and display PDF in Shiny

I am trying to show some PDFs from around the web in an app on shinyapps.io. Unfortunately, the standard way of using an iframe with the URL is not an option because of the mixed-content safeguards (the pdfs are served via http). I think that a possible option is to download the pdfs from the url then display them in an iframe from the local file, but I cannot get this to work with tempfile().

A sample app:

ui <- fluidPage(
  sidebarLayout(
      sidebarPanel(
        textInput("url", "add a url"),
        actionButton("button","hit the button"),
        h5("use case - embed a pdf user guide in the app - embed as a local pdf or from web URL")
      ), 
      mainPanel(
        tabsetPanel(
          tabPanel("PDF", 
                   htmlOutput("pdf")
                   )
          )
        )
      )
)

server <- function(input, output, session) {

  observeEvent(input$button, {
    temp <- tempfile(fileext = ".pdf")
    download.file(input$url, temp)

    output$pdf <- renderUI({
      tags$iframe(src=temp)
    })
  })
}

shinyApp(ui, server)

Sample pdf: http://www.pdf995.com/samples/pdf.pdf

When I open this in the browser I get an error in the browser console: Not allowed to load local resource: file:///C:/Users/.../Local/Temp/Rtmp8subWX/file19403a2a2fc8.pdf and nothing in the panel where the iframe is.

A similar attempt uploaded to shinyapps.io failed as well, showing a 404 Not Found error in the pdf viewer.

I think this may be an issue with how shiny/shinyapps.io deal with temp files, but can't quite figure it out. Thanks.

Upvotes: 3

Views: 2969

Answers (1)

HubertL
HubertL

Reputation: 19544

You need to download the PDF in binary mode in a subfolder of your current directory, then call addResourcePath to allow shiny to serve it:

  observeEvent(input$button, {
    pdf_folder <- "pdf_folder"
    if(!file.exists(pdf_folder))
      dir.create("pdf_folder")
    temp <- tempfile(fileext = ".pdf", tmpdir = "pdf_folder")
    download.file(input$url, temp, mode = "wb")
    addResourcePath("pdf_folder",pdf_folder)

    output$pdf <- renderUI({
      tags$iframe(src=temp)
    })
  })

Upvotes: 6

Related Questions