Download file from server to local directory using Shiny - r

I am not sure if I am understanding this correctly. Where should the data set that I want to download be in RStudio server? I do not want to deploy yet, so I am not using the Shiny server, but I want to use the download functionality and save the data set as a file in a local directory.
I have uploaded a file using Shiny fileInput and I have saved the file using copy.file(). I was told that the uploaded file is saved to the server. The file is called 0.tsv. Afterwards, I read that file and download it. The GUI works, but the file doe not get written to a file and saved to the local directory. My question is: is there any thing missing in my approach?
library(shiny)
ui <- fluidPage(
titlePanel('File download'),
sidebarLayout(
sidebarPanel(
selectInput("dataset", "Choose a dataset:",
choices = c("data")),
radioButtons("filetype", "File type:",
choices = c( "tsv")),
downloadButton('downloadData', 'Download')
),
mainPanel(
tableOutput('table')
)
)
)
function(input, output) {
datasetInput <- reactive({
# Fetch the appropriate data object, depending on the value
# of input$dataset.
data <- read.table("home/user/0.tsv")
switch(input$dataset,
"data" = data)
})
output$table <- renderTable({
datasetInput()
})
# downloadHandler() takes two arguments, both functions.
# The content function is passed a filename as an argument, and
# it should write out data to that filename.
output$downloadData <- downloadHandler(
# This function returns a string which tells the client
# browser what name to use when saving the file.
filename = function() {
paste(input$dataset, input$filetype, sep = ".")
},
# This function should write data to a file given to it by
# the argument 'file'.
content = function(file) {
sep <- switch(input$filetype, "tsv" = "\t")
# Write to a file specified by the 'file' argument
write.table(datasetInput(), file, sep = sep,
row.names = FALSE)
}
)
}
shinyApp(ui = ui, server = server)
ui <- fluidPage(
titlePanel('File download'),
sidebarLayout(
sidebarPanel(
selectInput("dataset", "Choose a dataset:",
choices = c("data")),
radioButtons("filetype", "File type:",
choices = c( "tsv")),
downloadButton('downloadData', 'Download')
),
mainPanel(
tableOutput('table')
)
)
)
function(input, output) {
datasetInput <- reactive({
# Fetch the appropriate data object, depending on the value
# of input$dataset.
data <- read.table("home/user/0.tsv")
switch(input$dataset,
"data" = data)
})
output$table <- renderTable({
datasetInput()
})
# downloadHandler() takes two arguments, both functions.
# The content function is passed a filename as an argument, and
# it should write out data to that filename.
output$downloadData <- downloadHandler(
# This function returns a string which tells the client
# browser what name to use when saving the file.
filename = function() {
paste(input$dataset, input$filetype, sep = ".")
},
# This function should write data to a file given to it by
# the argument 'file'.
content = function(file) {
sep <- switch(input$filetype, "tsv" = "\t")
# Write to a file specified by the 'file' argument
write.table(datasetInput(), file, sep = sep,
row.names = FALSE)
}
)
}
shinyApp(ui = ui, server = server)

Thanks very much for your response. Below is the correct way to do it. This works fine.
server <- function(input, output) {
# Reactive value for selected dataset ----
datasetInput <- reactive({
switch(input$dataset,
"params" = params)
})
# Table of selected dataset ----
output$table <- renderTable({
datasetInput()
})
# Downloadable csv of selected dataset ----
output$downloadData <- downloadHandler(
filename = function() {
paste(input$dataset, ".csv", sep = "")
},
content = function(file) {
write.table(datasetInput(), file, row.names = FALSE)
}
)
}

Related

Download multiple dataframes in multiple sheets of the same excel file in a shiny app

I wonderif there is a way to download 2 dataframes in the same excel file but in different sheet via shiny app.
library(shiny)
library(xlsx)
ui <- shinyUI(fluidPage(
titlePanel("Testing File upload"),
sidebarLayout(
sidebarPanel(
downloadButton("dl","Export in Excel")
),
mainPanel(
)
)
))
server <- shinyServer(function(input, output) {
output$dl <- downloadHandler(
filename = function() {
paste0("df_dmodel", "_Table", ".xls")
},
content = function(file){
tbl<-iris
tbl2<-mtcars
write.xlsx(tbl,tbl2 file,
sheetName = "Sheet1", row.names = FALSE)
}
)
})
shinyApp(ui = ui, server = server)
try changing your server code to this. Also, remember to open the app in your browser and not just the rstudio viewer (assuming your are using rstudio). Hope this helps!
server <- shinyServer(function(input, output) {
output$dl <- downloadHandler(
filename = function() {
paste0("df_dmodel", "_Table", ".xlsx")
},
content = function(file){
tbl<-iris
tbl2<-mtcars
sheets <- mget(ls(pattern = "tbl")) # getting all objects in your environment with tbl in the name
names(sheets) <- paste0("sheet", seq_len(length(sheets))) # changing the names in your list
writexl::write_xlsx(sheets, path = file) # saving the file
}
)
})
An alternative to Andrew's answer using write.xlsx from openxlsx with a list of dataframes.
library(shiny)
library(openxlsx)
ui <- shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
downloadButton("dl","Export in Excel")
),
mainPanel(
)
)
))
server <- shinyServer(function(input, output) {
output$dl <- downloadHandler(
filename = function() {
"test.xlsx"
},
content = function(filename){
df_list <- list(iris=iris, mtcars=mtcars)
write.xlsx(x = df_list , file = filename, row.names = FALSE)
}
)
})
shinyApp(ui = ui, server = server)

Got error in fread function when building shiny app

I supposed to read file from fileInput but when I ran the app I got this error:
Warning: Error in fread: input= must be a single character string containing a file name, a system command containing at least one space, a URL starting 'http[s]://', 'ftp[s]://' or 'file://', or, the input data itself containing at least one \n or \r
My Shiny Code:
library(shiny)
library(data.table)
library(DT)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("file","Operation Record",
multiple = TRUE,
buttonLabel = "Browse...",
placeholder = "No file selected",
accept = c(
"text/csv",
"text/comma-separated-values,text/plain",
".csv")
)
),
mainPanel(
DTOutput("table")
)
)
)
server <- function(input, output) {
output$table <- renderDT({
originalDataset <- fread(input = input$file$datapath,encoding = "UTF-8",
select = c("Date","ID","Type","EMail","ClientType"))
return(originalDataset)
})
}
# Run the application
shinyApp(ui = ui, server = server)
Any suggestions?Thank you in advance.
When you run the app, input$file is NULL, until you select a file. You need a req:
server <- function(input, output) {
output$table <- renderDT({
req(input$file)
originalDataset <- fread(input = input$file$datapath,encoding = "UTF-8",
select = c("Date","ID","Type","EMail","ClientType"))
return(originalDataset)
})
}

downloadHandler not working with observeEvent

I am trying to download a file using downloadHandler with observeEvent shiny but I am not able to download the file,
library(shiny)
load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_4850/datasets/movies.Rdata"))
ui <- fluidPage(
sidebarLayout(
# Input
sidebarPanel(
# Numeric input for number of rows to show
numericInput(inputId = "n_rows",
label = "How many rows do you want to see?",
value = 10),
# Action button to show
actionButton(inputId = "button",
label = "Show")
),
# Output:
mainPanel(
tableOutput(outputId = "datatable")
)
)
)
server <- function(input, output, session) {
# creating a reactive expression
df <- eventReactive(input$button, {
movies %>% head(input$n_rows)
})
# download a csv everytime when user click on show button
observeEvent(input$button, {
output$button <- downloadHandler(
filename = function() {
paste("data-", Sys.Date(), ".csv", sep="")
},
content = function(file) {
write.csv(df(), file)
}
)
cat("done downloading file \n")
})
# displays the data on the web in tabular format, data comes from reactive event
output$datatable <- renderTable({
df()
})
}
# Create a Shiny app object
shinyApp(ui = ui, server = server)
I was able to execute above code without any errors, but csv file is not downloading, i want to display the data table and download the displayed data on same button click event , how can i achieve this, Am I missing something, any help would be appreciated
Try this:
library(shiny)
library(dplyr)
load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_4850/datasets/movies.Rdata"))
ui <- fluidPage(
sidebarLayout(
# Input
sidebarPanel(
# Numeric input for number of rows to show
numericInput(inputId = "n_rows",
label = "How many rows do you want to see?",
value = 10),
# Action button to show
downloadButton('downloadData', 'Download data')
),
# Output:
mainPanel(
tableOutput(outputId = "datatable")
)
)
)
server <- function(input, output, session) {
# Reactive value for selected dataset ----
df <- reactive({
movies %>% head(input$n_rows)
})
output$datatable <- renderTable({
df()
})
output$downloadData <- downloadHandler(
filename = function() {
paste("dataset-", ".csv", sep = "")
},
content = function(file) {
write.csv(df(), file, row.names = FALSE)
})
}
# Create a Shiny app object
shinyApp(ui = ui, server = server)

passing on data from observe function to download

I got stuck on my first shiny app again. So far the App was runing fine, but now I wanted to download the plot I generated and I can not work out how to get the results out of the observe function.
As I can not generate the plot outside the observe function, I was thinking I would assign the necessary data to a global variable useing <<-, but if I run a reactive function e.g. df.selected.columns() this seem to cause errors.
Can someone give me a hint how to proceed?
Thank you so much for any suggestions! Aishe
Here is me code:
ui <- shinyServer(
fluidPage(
tabsetPanel(
tabPanel("Data upload",
titlePanel("Data upload"),
sidebarLayout(
sidebarPanel(
fileInput("file1", "Choose CSV File",multiple = TRUE, accept = c("text/csv","text/comma-separated-values,text/plain",".csv")),
tags$hr(),
checkboxInput("header", "Header", TRUE), radioButtons("sep", "Separator", choices = c(Comma = ",", Semicolon = ";",Tab = "\t"), selected = ","),
tags$hr(),
checkboxInput("disp", "Display",TRUE),
tags$hr(),
uiOutput("choose_first_column"),
uiOutput("choose_second_column"),
br()
),
mainPanel(
tableOutput("contents"),
tags$hr(),
tableOutput("tab"),
tags$hr(),
uiOutput("download"),
plotOutput("headplot")
)
)
),
tabPanel("2","2"
)
)
)
)
server <- shinyServer(
function(input, output) {
observe({
req(input$file1)
df <- read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
output$contents <- renderTable({
(head(df))})
output$choose_first_column <- renderUI({
colnames <- names(df)
selectInput("column_1", "Choose Date column",
choices = colnames,
selected = colnames)})
output$choose_second_column <- renderUI({
colnames <- names(df)
selectInput("column_2", "Choose Variable column",
choices = colnames,
selected = colnames)})
df.selected.columns <- reactive({
df.columns <- df[,c(input$column_1,input$column_2)]
return(df.columns)
})
output$tab <- renderTable({
(head(df.selected.columns()))
})
Plot1 <- reactive({
plot(head(df.selected.columns()[,2]))
})
output$headplot <- renderPlot({
Plot1()
})
# This comes closest to what I wanted to do. However, now I can not select the columns anymore.
# try(result <<- head(df.selected.columns()[,2]),silent=T)
# With this line it crushes straight away
# result <<- head(df.selected.columns()[,2])
})
output$download <- renderUI({
if(!is.null(input$column_1) & !is.null(input$column_2)) {
downloadButton('OutputPlot', 'Download Plot')
}
})
output$OutputPlot <- downloadHandler(
filename = function() {
paste('plot', '.pdf', sep='')
},
content=function(file){
pdf(file)
plot(result)
dev.off()
})
})
runApp(list(ui = ui, server = server))
Input data example:
date time level
01.01.2000 00:00:00 0.3724
01.01.2000 01:00:00 0.192
01.01.2000 02:00:00 -0.0252
Remove the observe
Make the loaded file a reactive
Update all references to df to df() since it's now a reactive expression
Add appropriate req() functions to prevent error messages
In your downloadHandler you have plot(result), but there's no such thing as result. You want Plot() or plot(df.selected.columns())
You should be confirming that your selected delimiter is actually splitting the loaded table correctly before your return the loaded table. Without that, you'll get errors and strange results/
Here's the updated df and downloadHandler functions to get you started:
df <- reactive({
req(input$file1)
read.csv(input$file1$datapath,
header = input$header,
sep = input$sep,
quote = input$quote)
})
output$OutputPlot <- downloadHandler(
filename = function() {
paste('plot', '.pdf', sep='')
},
content=function(file){
pdf(file)
plot(head(df.selected.columns()[,2]))
dev.off()
})

Downloading multiple reactive objects containing data tables

I have multiple tables in reactive objects in my shiny app (RA_s,Per), and I download each separately. Now, I'm trying to download one zip file containing all of this tables using a download button.
Here is my code, I don't know how to complete downloadHandler function. I want to download a zip file which contain 2 csv files RA_s and Per.
Code
shinyServer(function(input, output) {
RA_s <- reactive({
iris
})
Per <- reactive({
sepal1 <- RA_s()["Sepal_Length"]
sepal2 <- RA_s()["Sepal_Width"]
value = sepal1*sepal2
c = cbind(RA_s(),value)
})
output$downloadData <- downloadHandler(
filename = function() {
paste0("output", ".zip")
},
content = function(file) {
...
})
})
sidebar <- dashboardSidebar(
sidebarMenu(
menuItem("Download", tabName = "d")
)
body<- dashboardBody(
tabItems(
tabItem(tabName = "d",
downloadButton('downloadData', 'Download')
)
)
dashboardPage(
dashboardHeader(title = "Valo"),
sidebar,
body
)
You can first save the zip files, and then zip them, as follows:
library(shiny)
server<- shinyServer(function(input, output) {
RA_s <- reactive({
iris
print(iris)
})
Per <- reactive({
sepal1 <- RA_s()["Sepal.Length"]
sepal2 <- RA_s()["Sepal.Width"]
value = sepal1*sepal2
c = cbind(RA_s(),value)
})
output$downloadData <- downloadHandler(
filename = 'two_csvs.zip',
content = function(fname) {
write.csv(RA_s(), file = "csv1.csv", sep =",")
write.csv(Per(), file = "csv2.csv", sep =",")
zip(zipfile=fname, files=c("csv1.csv","csv2.csv"))
},
contentType = "application/zip"
)
})
ui<- shinyUI(
downloadButton('downloadData', 'Download')
)
shinyApp(ui,server)
You can specify a subdirectory of course, to keep your directory clean. Hope this helps!

Resources