Downloads
downloadButton() and downloadHandler()
Try it first: choose a dataset, click Select dataset, then use the two download buttons.
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [viewer]
#| viewerHeight: 750
## file: ui.R
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("dataset", "Choose a dataset:",
choices = c("rock", "pressure", "cars")),
actionButton("load", "Select dataset")
),
mainPanel(
plotOutput("graph"),
downloadButton("downloadPlot", "Download plot"),
verbatimTextOutput("summary"),
downloadButton("downloadSummary", "Download summary")
)
)
)
## file: server.R
library(shiny)
server <- function(input, output, session) {
dataInput <- eventReactive(input$load, {
switch(input$dataset,
rock = rock,
pressure = pressure,
cars = cars)
})
# descriptive statistics of the first two columns
ddata <- reactive({
df <- dataInput()[, 1:2]
data.frame(variable = names(df),
mean = sapply(df, mean),
sd = sapply(df, sd),
row.names = NULL)
})
output$graph <- renderPlot({
plot(dataInput()[, 1:2])
})
output$summary <- renderPrint({
ddata()
})
# downloadHandler = the "render" function of downloadButton()
output$downloadSummary <- downloadHandler(
filename = function() {
paste0("descriptive-", input$dataset, ".csv")
},
content = function(file) {
write.csv(ddata(), file, row.names = FALSE)
}
)
output$downloadPlot <- downloadHandler(
filename = function() {
paste0("plot-", input$dataset, ".png")
},
content = function(file) {
png(file, width = 800, height = 600)
plot(dataInput()[, 1:2])
dev.off()
}
)
}
How it works
Downloads follow the usual pair:
- in
ui.R,downloadButton("id", "Label") - in
server.R,output$id <- downloadHandler(...)
output$downloadSummary <- downloadHandler(
1 filename = function() {
paste0("descriptive-", input$dataset, ".csv")
},
2 content = function(file) {
write.csv(ddata(), file, row.names = FALSE)
}
)- 1
- A function that returns the name of the file the user will get
- 2
-
A function that writes the content into
file(a temporary path chosen by Shiny)
For a plot, content opens a graphic device, draws the plot and closes the device:
content = function(file) {
png(file, width = 800, height = 600)
plot(dataInput()[, 1:2])
dev.off()
}The code
#| '!! shinylive warning !!': |
#| shinylive does not work in self-contained HTML documents.
#| Please set `embed-resources: false` in your metadata.
#| standalone: true
#| components: [editor, viewer]
#| layout: vertical
#| viewerHeight: 750
## file: ui.R
library(shiny)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("dataset", "Choose a dataset:",
choices = c("rock", "pressure", "cars")),
actionButton("load", "Select dataset")
),
mainPanel(
plotOutput("graph"),
downloadButton("downloadPlot", "Download plot"),
verbatimTextOutput("summary"),
downloadButton("downloadSummary", "Download summary")
)
)
)
## file: server.R
library(shiny)
server <- function(input, output, session) {
dataInput <- eventReactive(input$load, {
switch(input$dataset,
rock = rock,
pressure = pressure,
cars = cars)
})
# descriptive statistics of the first two columns
ddata <- reactive({
df <- dataInput()[, 1:2]
data.frame(variable = names(df),
mean = sapply(df, mean),
sd = sapply(df, sd),
row.names = NULL)
})
output$graph <- renderPlot({
plot(dataInput()[, 1:2])
})
output$summary <- renderPrint({
ddata()
})
# downloadHandler = the "render" function of downloadButton()
output$downloadSummary <- downloadHandler(
filename = function() {
paste0("descriptive-", input$dataset, ".csv")
},
content = function(file) {
write.csv(ddata(), file, row.names = FALSE)
}
)
output$downloadPlot <- downloadHandler(
filename = function() {
paste0("plot-", input$dataset, ".png")
},
content = function(file) {
png(file, width = 800, height = 600)
plot(dataInput()[, 1:2])
dev.off()
}
)
}
Exercise
Add a download button to your explore-a-dataset app that saves newdata() as a CSV file.