Reputation: 851
I would like to allow my users to save their current workspace to a directory of their choosing. I am not able to make it work.
Below is my code. Any suggestions? Thanks in advance.
ui.R:
shinyUI(fluidPage(
titlePanel("Save RData"),
sidebarLayout(
sidebarPanel(
),
mainPanel(
downloadButton('download_structure', "Save")
)
)
))
server.R
shinyServer(function(input, output) {
output$download_structure <- downloadHandler(
filename = function() {paste("Test.RData")},
content = function(file) {
list = ls(all.names = TRUE)
}
)
})
EDIT:
I also tried the following codes.
I entered "C:/Users/MyName/Desktop/" or "C://Users//MyName//Desktop//" as the input$RDdata_dir_save. Both are not working.
Any suggestions would be really appreciated!
snippets of my ui.R:
textInput("RData_name_save", "RData name"),
textInput("RData_dir_save", "Save directory"),
snippets of my server.R:
tempdir <- paste0(input$RData_dir_save,input$RData_name_save,'.RData"')
save.image(file=eval(parse(text=tempdir)))
Upvotes: 1
Views: 1239
Reputation: 563
the problem is that objects are not in the shiny environment and save.image() does not save anything interesting.
maybe this is of interest, copied from https://groups.google.com/forum/#!topic/shiny-discuss/_iLbT3Aaz3I
I often wish that I could interactively work within my shiny application interactively, similar to using browse()in a function., and sometimes I use a shiny GUI to get to a state where I just want to save things.
So, I wrote something that can save all the shiny application objects,which uses Hadley's pryr package to recursively list the objects. So you need this somewhere (I think it belongs in global.R or server.R) library(pryr)
In ui.R you need an action button. You could add this to one of the existing shiny examples. actionButton("save_objs", "Save Objects")
In server.R I have this code, which listens to save_objs:
observeEvent(input$save_objs, {
# Run whenever save_objs button is pressed
print("** saving objects! **")
## Print the objects being saved
print(rls())
# ## Put objects into current environment
for(obj in unlist(rls())) {
if(class(get(obj, pos = -1))[1] == "reactive"){
## execute the reactive objects and put them in to this
## environment i.e. into the environment of this function
assign(obj, value = eval(call(obj)))
} else {
## grab the global variables and put them into this
## environment
assign(obj, value = get(obj, pos = -1))
}
}
input_copy <- list()
for(nm in names(input)){
# assign(paste0("input_copy$", nm), value <- input[[nm]])
input_copy[[nm]] <- input[[nm]]
}
## save objects in current environment
save(list = ls(), file = "shiny_env.Rdata", envir = environment())
print("** done saving **")
})
I use print statements liberally during development, feel free to omit them.
This took me a while to figure out, so hopefully it will save someone else time (maybe even me later when I forget and google "R how to save objects in shiny").
As a side note, I can't understand how the rls can find the environment with the reactive objects. It's not in my current budget to buy Hadley's Advanced Programming in R, so I'll have to wait to find out. I tried to get the objects directly with various combinations of parent.frame and parent.env, but I could only find Shiny internal objects and objects in my normal search path. So... there's some clever stuff in that pryr package.
Upvotes: 1
Reputation: 1631
I've tried a workaround using directoryInput
and taking file name from user. This solution doesn't use downloadHandler
functionality, it's just a temporary workaround.
For the selection of directory, i've used directoryInput
as configured here.
ui.R
library(shiny)
shinyUI(fluidPage(
fluidRow(
column(
width = 10,
titlePanel("Save RData"),
directoryInput('directory', label = 'select directory'),
hr(),
textOutput("dir"),
textInput("file_name","give file name"),
actionButton("save","Save RData"),
conditionalPanel(
condition="output.saved!=0",
h4('Saved successfully')
)
)
)
))
Note:
conditionalPanel
is displayed after actionButton
triggers the saving in sever.R
server.R
library(shiny)
shinyServer(function(input, output, session) {
observeEvent(input$save,{
SaveRData()
})
observeEvent(
ignoreNULL = TRUE,
eventExpr = {
input$directory
},
handlerExpr = {
if (input$directory > 0) {
# condition prevents handler execution on initial app launch
path = choose.dir(default = readDirectoryInput(session, 'directory'))
updateDirectoryInput(session, 'directory', value = path)
}
}
)
output$directory = renderText({
readDirectoryInput(session, 'directory')})
SaveRData <- reactive({
if(!(is.null(dir) && is.null(input$save) && is.null(input$file_name))){
dir <- readDirectoryInput(session, 'directory')
file_name <- paste(input$file_name,".RData", sep="")
save.image(file = paste(dir,file_name, sep = "\\"))
}
})
output$saved<-reactive({input$save})
outputOptions(output, 'saved', suspendWhenHidden = FALSE)
})
As soon as save
button is pressed, it triggers SaveRData
function which basically uses save.image(...)
with parameters from input
.
Upvotes: 0