R Shiny: Uploading a file on button click

15,790

fileInput upload the file directly so I suggest you to create your own "fileInput".

Here is how I shall proceed :

Server.R

library(shiny)

shinyServer(function(input, output, session) {

  observe({

    if (input$browse == 0) return()

    updateTextInput(session, "path",  value = file.choose())
  })

  contentInput <- reactive({ 

    if(input$upload == 0) return()

    isolate({
      writeLines(paste(readLines(input$path), collapse = "\n"))
    })
  })

  output$content <- renderPrint({
    contentInput()
  })

})

Ui.R

library(shiny)

shinyUI(pageWithSidebar(

  headerPanel("Example"),

  sidebarPanel(
    textInput("path", "File:"),
    actionButton("browse", "Browse"),
    tags$br(),
    actionButton("upload", "Upload Data")
  ),

  mainPanel(
    verbatimTextOutput('content')
  )

))

In "Server.R" firstly we update the value of the text input each time the action button "Browse" is clicked.

"contentInput" is a reactive function, it will be reexecuted when input values (contained in the body of the function) are changed, "input$upload" here, and not when "input$path" changed because we isolate it. If we didn't isolate the part containing "input$path", the "contentInput" will be reexecuted each times we browse a new file and then the upload button will be useless here.

And then we return the result of "contentInput" in "output$content".

Hope this help.

EDIT ## :

I realized that if you cancel the file choosing it produce an error and the shiny app crash, then you should use this function by Henrik Bengtsson (https://stat.ethz.ch/pipermail/r-help/2007-June/133564.html) :

file.choose2 <- function(...) {
  pathname <- NULL;
  tryCatch({
    pathname <- file.choose();
  }, error = function(ex) {
  })
  pathname;
}
Share:
15,790
tejas_kale
Author by

tejas_kale

Updated on June 18, 2022

Comments

  • tejas_kale
    tejas_kale almost 2 years

    I know that there is quite some material already available on the web to answer my question but none of them seem to work for me. I suppose that's because I do not understand Shiny's reactive programming well.

    So, I wish to create an interface that lets a user select a file using fileInput and upload it only on clicking the Upload button. I tried a few solutions from various forums but none worked. Following is my latest attempt:

    #ui.R
    
    library(shiny)
    
    shinyUI(pageWithSidebar(
    
    
        headerPanel(""),
    
        sidebarPanel(
    
                fileInput("in_file", "Input file:",
                        accept=c("txt/csv", "text/comma-separated-values,text/plain", ".csv")),
                checkboxInput(inputId="is_header", label="Does the input file have column names?", value=TRUE),
                actionButton("upload_data", "Upload Data"),
        ),
        mainPanel(
            tabsetPanel(
                        tabPanel("Original Data", tableOutput("orig_data"))
            )
        )
    ))
    
    
    #server.R
    
    library(shiny)
    
    shinyServer(function(input, output, session) {
    
        ra_dec_data <- reactive({
                if(input$upload_data==0)
                        return(NULL)
    
                return(isolate({
                        head(read_data(input$in_file$datapath, input$in_file$is_header), 50)
                }))
        })
    
        output$orig_data <- renderTable({
            ra_dec_data()
        })
    })
    

    The issue I face is that the file gets uploaded as soon as it is selected and the Upload button is unresponsive.

    My guess is that what I have done does not make sense, so please accept my apologies for doing this terribly. Any help would be really appreciated. Thanks!

  • Vincent
    Vincent about 10 years
    It is important the note that file.choose will only work when you run your Shiny app locally. I am not sure what you mean by 'upload the file directly'.
  • Julien Navarre
    Julien Navarre about 10 years
    OP wants to "select a file using fileInput and upload it only on clicking the Upload button." fileInput doesn't wait for an user action to upload the datas.