upload and view a pdf in R shiny - r

I have a simple shiny app in R for reading a PDF file from the user and display it. I can't seem to get it to work. On the shiny server in the www directory I see a 1 KB file with the name "myreport.pdf" that just has the first character
library(shiny)
ui <- shinyUI(fluidPage(
titlePanel("Testing File upload"),
sidebarLayout(
sidebarPanel(
fileInput('file_input', 'upload file ( . pdf format only)', accept = c('.pdf'))
),
mainPanel(
uiOutput("pdfview")
)
)
))
server <- shinyServer(function(input, output) {
observe({
req(input$file_input)
test_file <- readBin(input$file_input$datapath, what="character")
writeBin(test_file, "www/myreport.pdf")
})
output$pdfview <- renderUI({
tags$iframe(style="height:600px; width:100%", src="myreport.pdf")
})
})
shinyApp(ui = ui, server = server)

I think the issue is with the binary reading and writing. Instead trying to copy the files using file.copy seems to work. Also I've taken the iframe inside observeEvent for the iframe to update every time the pdf is uploaded in the same session.
Updated Code:
library(shiny)
ui <- shinyUI(fluidPage(
titlePanel("Testing File upload"),
sidebarLayout(
sidebarPanel(
fileInput('file_input', 'upload file ( . pdf format only)', accept = c('.pdf'))
),
mainPanel(
uiOutput("pdfview")
)
)
))
server <- shinyServer(function(input, output) {
observe({
req(input$file_input)
#test_file <- readBin(input$file_input$datapath, what="raw")
#writeBin(test_file, "myreport.pdf")
#cat(input$file_input$datapath)
file.copy(input$file_input$datapath,"www", overwrite = T)
output$pdfview <- renderUI({
tags$iframe(style="height:600px; width:100%", src="0.pdf")
})
})
})
shinyApp(ui = ui, server = server)

Related

Cannot paste network path to list files

i've built an app that allow users to paste a folder path so that files inside that folder can be listed and selected. The app works when i set the path globally but i really need users to be able to stipulate their path. The path needs to be a network path as we use Azure/Databricks...
library(dplyr)
library(shinyWidgets)
library(shinythemes)
library(DT)
fpath <- '/dbfs/dbfs/Analytics/ShinyApp' #example path
# Define UI
ui <- fluidPage(
theme = shinytheme("spacelab"),
navbarPage(
"App",
tabPanel(
"Setup Project",
sidebarPanel(
textInput("v_inpath", "Specify File Path:", ""),
actionButton("Setpath", "Set Path"),
selectInput("selectfile", "Select File to Analyse",choice = list.files("ppath", pattern = ".csv")) #list of files should show up here
), # sidebarPanel
mainPanel(verbatimTextOutput("ppath")) # mainPanel
) #tabPanel
) # navbarPage
) # fluidPage
# Define server function
server <- function(input, output, session) {
observeEvent(input$Setpath,{
output$ppath <-reactive({paste0(input$v_inpath)})
})
} # server
# Create Shiny object
shinyApp(ui = ui, server = server)
In the mainPanel, i can see the path being pasted correctly as text (as you can see i'm using verbatimTextOutput("ppath")). The list of files contained in the specified folder should show up but it does not work as no list is available... Thank you in advance for your help
You need renderUI
You should avoid to put an output element inside an observer
You could use the shinyFiles package or the jsTreeR package to select the path
Code:
library(shiny)
# Define UI
ui <- fluidPage(
navbarPage(
"App",
tabPanel(
"Setup Project",
sidebarPanel(
textInput("v_inpath", "Specify File Path:", ""),
actionButton("Setpath", "Set Path"),
uiOutput("selectfileUI")
), # sidebarPanel
mainPanel(verbatimTextOutput("ppath")) # mainPanel
) #tabPanel
) # navbarPage
) # fluidPage
# Define server function
server <- function(input, output, session) {
output[["selectfileUI"]] <- renderUI({
req(input[["Setpath"]])
files <- list.files(input[["v_inpath"]], pattern = ".csv")
selectInput("selectfile", "Select File to Analyse", choices = files)
})
output[["ppath"]] <- renderPrint({
input[["v_inpath"]]
})
} # server
# Create Shiny object
shinyApp(ui = ui, server = server)
EDIT: feedback
Also, you can use the shinyFeedback package to print a message when the path is not valid:
library(shiny)
library(shinyFeedback)
# Define UI
ui <- fluidPage(
useShinyFeedback(), # don't forget this line
navbarPage(
"App",
tabPanel(
"Setup Project",
sidebarPanel(
textInput("v_inpath", "Specify File Path:", ""),
actionButton("Setpath", "Set Path"),
uiOutput("selectfileUI")
), # sidebarPanel
mainPanel(verbatimTextOutput("ppath")) # mainPanel
) #tabPanel
) # navbarPage
) # fluidPage
# Define server function
server <- function(input, output, session) {
Check <- eventReactive(input[["Setpath"]], {
dir.exists(input[["v_inpath"]])
})
Files <- reactive({
req(Check())
list.files(input[["v_inpath"]], pattern = ".csv")
})
observeEvent(input[["Setpath"]], {
hideFeedback("v_inpath")
show <- !Check() || length(Files()) == 0
if(show) {
if(Check()) {
text <- "No CSV file in this folder"
} else {
text <- "Invalid path"
}
showFeedbackWarning("v_inpath", text)
} else {
hideFeedback("v_inpath")
}
})
output[["selectfileUI"]] <- renderUI({
req(Files())
selectInput("selectfile", "Select File to Analyse", choices = Files())
})
output[["ppath"]] <- renderPrint({
input[["v_inpath"]]
})
} # server
# Create Shiny object
shinyApp(ui = ui, server = server)

R Shiny import multiple PDFs and view them one by one using actionButton

I have the below app that can view one pdf after import. However I want to be able to import multiple PDFs (this can already be done), and click the Next PDF actionButton to view the next PDF. All the way till the last imported PDF, how can I do that?
If the below code is not working to view one pdf, please ensure you have a www folder in the same directory of your app.R.
library(shiny)
ui <- shinyUI(fluidPage(
titlePanel("Testing File upload"),
sidebarLayout(
sidebarPanel(
fileInput('file_input', 'upload file ( . pdf format only)',
accept = c('.pdf'),multiple = T),
actionButton("next_pdf", "Next PDF")
),
mainPanel(
uiOutput("pdfview")
)
)
))
server <- shinyServer(function(input, output) {
observe({
req(input$file_input)
file.copy(input$file_input$datapath,"www", overwrite = T)
output$pdfview <- renderUI({
tags$iframe(style="height:1200px; width:100%", src="0.pdf")
})
})
})
shinyApp(ui = ui, server = server)
I have worked out a solution! I use reactiveVal for variable x, and each time the actionButton is clicked, x will increase 1. On that basis, I can view the PDF one by one by specifying datapath[]. It can be very useful for people with multiple pdf files.
library(shiny)
ui <- shinyUI(fluidPage(
titlePanel("Testing File upload"),
sidebarLayout(
sidebarPanel(
fileInput('file_input', 'upload file ( . pdf format only)',
accept = c('.pdf'),multiple = T),
tableOutput("files"),
actionButton("next_pdf", "Next PDF"),
textOutput("testing")
),
mainPanel(
uiOutput("pdfview")
)
)
))
server <- shinyServer(function(input, output) {
x = reactiveVal(1)
output$files <- renderTable({input$file_input})
observeEvent(input$file_input,{
file.copy(input$file_input$datapath[1],"www", overwrite = T)
output$pdfview <- renderUI({
tags$iframe(style="height:1200px; width:100%", src="0.pdf")
})
})
observeEvent(input$next_pdf,{
x(x()+1)
file.rename(input$file_input$datapath[x()], "0.pdf")
file.copy("0.pdf","www", overwrite = T)
output$pdfview <- renderUI({
tags$iframe(style="height:1200px; width:100%", src="0.pdf")
})
output$testing = renderText(x())
})
})
shinyApp(ui = ui, server = server)

How can I provide a location in R shiny where the submitted file should be saved?

The code below takes the user's input file (filename1) and uploads it to the same directory with a new name (example: userFile_filename1) in the same directory. I'd want to upload the input file to a separate location. In R shiny, how can I set a path of my choice?
library(shiny)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Select file to upload' )
),
mainPanel(
h4('List of uploaded files:')
,verbatimTextOutput('fileList')
)
))
)
server <- shinyServer(function(input, output) {
observe({
if (is.null(input$file1) ) { return(NULL) }
file.copy(from = input$file1$datapath, to = paste0('userFile_',input$file1$name ) )
})
output$fileList <- renderText({
input$file1
dir(pattern = 'userFile_')
})
})
shinyApp(ui, server)

shinyFiles library not working with "read.csv"

I am trying to play with shinyFiles library and while I figured out the UI part of the shinyFiles, I can't get the server part working. Here is my code so far
library(shiny)
library(shinyFiles)
ui <- shinyUI(pageWithSidebar(
headerPanel(
'Selections with shinyFiles',
'shinyFiles example'
),
sidebarPanel(
shinyFilesButton('file', 'File select', 'Please select a file', FALSE)
),
mainPanel(
tags$h4('The output of a file selection'),
tableOutput("contents")
)
))
server <- shinyServer(function(input, output, session) {
shinyFileChoose(input, 'file', roots=c(wd='/home/rstudio'), filetypes=c('', 'csv'))
output$contents <- renderTable({
df <- read.csv(input$file)
print(head(df))
})
})
runApp(list(
ui=ui,
server=server
))
This is the error that I am getting
Warning: Error in read.table: 'file' must be a character string or connection
I just want to make the server side to print the header of the file that I chose with shinyFilesButton. I don't understand what I am doing wrong here.
You need to use parseFilePaths https://www.rdocumentation.org/packages/shinyFiles/versions/0.3.2/topics/parseFilePaths in order to get parse the file name. Then $datapath should be used to get the file name.
library(shiny)
library(shinyFiles)
ui <- shinyUI(pageWithSidebar(
headerPanel(
'Selections with shinyFiles',
'shinyFiles example'
),
sidebarPanel(
shinyFilesButton('file', 'File select', 'Please select a file', FALSE)
),
mainPanel(
tags$h4('The output of a file selection'),
tableOutput("contents")
)
))
server <- shinyServer(function(input, output, session) {
shinyFileChoose(input, 'file', roots=c(wd='.'), filetypes=c('', 'csv'))
output$contents <- renderTable({
inFile <- parseFilePaths(roots=c(wd='.'), input$file)
if( NROW(inFile)) {
df <- read.csv(as.character(inFile$datapath))
print(head(df))
}
})
})
runApp(list(
ui=ui,
server=server
))
Note: I changed the root path in the above code to allow it to run on my system.
This is related to: Loading data files with ShinyFiles

Get the name of uploaded file as a variable in Shiny

I am creating a Shiny App where one of the sections of a Venn Diagram will be named after the uploaded file(done by user). For example, if someone uploads a file ClientXYZ.csv, one section of the Venn diagram will be named "ClientXYZ"
Is it possible to do this in Shiny?
Its not clear without a reproducible example, but you can grab the name of the file with input and name.
library(shiny)
ui <- fluidPage(
titlePanel("Grabbing my file name"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Select your file',
accept = c(
'text/csv',
'text/comma-separated-values',
'.csv'
)
)
),
mainPanel(
textOutput("myFileName")
)
)
)
server <- function(input, output) {
file_name <- reactive({
inFile <- input$file1
if (is.null(inFile))
return(NULL)
return (stringi::stri_extract_first(str = inFile$name, regex = ".*(?=\\.)"))
})
output$myFileName <- renderText({ file_name() })
}
# Run the application
shinyApp(ui = ui, server = server)

Resources