1

Shiny has a nice fileInput() function for allowing the user to browse directories and select the file to upload into the App. Extracted from https://shiny.rstudio.com/reference/shiny/1.7.0/fileInput.html, here's the MWE:

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      fileInput("file1", "Choose CSV file to upload", accept = ".csv"),
      checkboxInput("header", "Header", TRUE)
    ),
    mainPanel(
      tableOutput("contents")
    )
  )
)
  
server <- function(input, output) {
  output$contents <- renderTable({
    file <- input$file1
    ext <- tools::file_ext(file$datapath)
      
    req(file)
    validate(need(ext == "csv", "Please upload a csv file"))
  
    read.csv(file$datapath, header = input$header)
  })
}
  
shinyApp(ui, server)

I'm using this in my App for retrieving data, I really like it. However, I'm looking for a similar feature where the user can save a dataframe that results from running the App in a similar way, by browsing directories to choose a location to save the file and selecting a file name. Key is the ability to browse local directories. Any ideas how to accomplish this? Preferably in a way as simple as fileInput().

Files will be .csv, though I'm thinking about .xls too.

1
  • 1
    Usually this is done with a downloadButton. After pressing the button the browser allows the user to select a directory and a filename. Commented Nov 18, 2021 at 12:38

2 Answers 2

1

You can use downloadButton in ui and downloadHandler in server as follows:

library(shiny)

ui <- fluidPage(
        sidebarLayout(
                sidebarPanel(
                        fileInput("file1", "Choose CSV file to upload", accept = ".csv"),
                        checkboxInput("header", "Header", TRUE),
                        downloadButton("download")
                ),
                mainPanel(
                        tableOutput("contents"),
                )
        )
)

server <- function(input, output) {
        output$contents <- renderTable({
                file <- input$file1
                ext <- tools::file_ext(file$datapath)
                
                req(file)
                validate(need(ext == "csv", "Please upload a csv file"))
                
                read.csv(file$datapath, header = input$header)
        })
        
        output$download <- downloadHandler(
                filename = function() {
                        paste0(input$file1, ".csv")
                },
                content = function(file) {
                        write.csv(contents(), file)
                }
        )
}

shinyApp(ui, server)
Sign up to request clarification or add additional context in comments.

1 Comment

This answer confused me for a moment. I don't get the file browser when I click on the download button. Then it occurred to me that I open my shiny apps in Chrome. If using the RStudio built-in browser, I get the file browser (I'm using Windows, for what it's worth). It seems some of these behaviors may be browser dependent (and possibly subject to group policy)
0

Here's a really basic example that invokes file.choose when you click on the action button.

library(shiny)

shinyApp(
  ui = 
    fluidPage(
      textInput(inputId = "txt_to_save", 
                label = "Enter text to save to a file"),
      actionButton(inputId = "btn_save_txt", 
                   label = "Save Text to File")
    ),
  
  server = 
    shinyServer(function(input, output, session){
      
      observeEvent(
        input$btn_save_txt, 
        {
          dest_file <- file.choose()
          write(input$txt_to_save, 
                dest_file)
        }
      )
      
    })
)

In practice, if you wanted to have the file name created by the application, but the directory chosen by the user, you could also use choose.dir().

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.