【问题标题】:Save/download multiple objects from the app with one save button使用一个保存按钮从应用程序保存/下载多个对象
【发布时间】:2020-07-15 18:24:30
【问题描述】:

上下文:我有一个应用程序根据用户的选择转换数据。它在此过程中创建了一些表格和绘图。

目标:一键将过程中创建的一些对象保存到一个新文件夹中。

以前的研究: 下面的代码使用downloadHandler() 和一些函数来保存对象here。它似乎不允许将多个对象传递给downloadHandler()。我知道可以将这些对象堆叠在一个列表中然后保存它,但如果可能的话,我想避免这样做,而是获取多个文件(如 .txt 或 .png,...)

这是一个使用 R 中包含的数据集(mtcarsiris)的数据非常少的可重现示例。

library(shiny)

ui <- fluidPage(
    downloadButton("save", "Save") # one click on this button to save df1 AND df2 tables in a new folder
)

server <- function(input, output) {
    # my real app does multiple changes on datasets based on user choices
    df1 = mtcars[1:10,]
    df2 = iris[1:10,]

    # Now I want to save df1 and df2 objects with 1 click on the "Save" button

    output$save = downloadHandler(
        filename = function(){ paste("example", ".txt", sep = " ") },
        content = function(file) { write.table(df1, file) }
    )
}

# Run the application 
shinyApp(ui = ui, server = server)

非常感谢您的帮助和建议!

【问题讨论】:

标签: r shiny


【解决方案1】:

正如链接帖子的 cmets 中所述,更改工作目录通常不是一个好主意(在这种情况下是不必要的)。虽然对于少量文件无关紧要,但创建路径的paste0 调用不需要在for 循环中,因为它是矢量化的。这也消除了动态增长fs 向量的需要(通常也是一种不好的做法)。最后,我的zip 实用程序不在我的路径上,这导致utils::zip 失败(您可以在函数调用中指定路径,否则它会检查环境变量R_ZIPCMD 并默认为'zip'假设它在路上)。

我一般同意接受的答案,但这里有一个替代解决方案,使用 zip::zipr 函数代替(也使用 walk 而不是 for 循环)

library(shiny)
library(purrr)
library(zip)

ui <- fluidPage(
  downloadButton("save", "Save") # one click on this button to save df1 AND df2 tables in a new folder
)

server <- function(input, output) {
  # my real app does multiple changes on datasets based on user choices
  df1 <- mtcars[1:10,]
  df2 <- iris[1:10,]

  # need to names these as user won't be able to specify
  fileNames <- paste0("sample_", 1:2, ".txt")

  output$save = downloadHandler(
    filename = function(){ paste0("example", ".zip") },
    content = function(file) { 

      newTmpDir <- tempfile()
      if(dir.create(newTmpDir)){

        # write data files
        walk2(list(df1, df2), fileNames, 
                        ~write.table(.x, file.path(newTmpDir, .y))
        )

        # create archive file
        zipr(file, files = list.files(newTmpDir, full.names = TRUE))

      }
    },
    contentType = "application/zip"
  )
}

【讨论】:

  • 非常感谢您的明确回答。我尝试不成功地使用 zip 包。我相信您的经验并按照您的建议实施。
猜你喜欢
  • 1970-01-01
  • 2014-11-23
  • 2013-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-10
  • 2020-03-22
相关资源
最近更新 更多