Сохранить / загрузить несколько объектов из приложения с помощью одной кнопки сохранения - PullRequest
0 голосов
/ 03 апреля 2020

Контекст: У меня есть приложение, преобразующее данные в соответствии с выбором пользователя. Он создает несколько таблиц и графиков в процессе.

Цель: сохранить несколько объектов, созданных в процессе, в одну новую папку одним нажатием кнопки.

Предыдущие исследования: код ниже сохраняются объекты с использованием downloadHandler() и некоторых функций, представленных здесь . Кажется, он не позволяет передавать несколько объектов в downloadHandler(). Я знаю, что можно поместить эти объекты в список и затем сохранить его, но, если возможно, я бы хотел избежать этого и вместо этого получить несколько файлов (например, .txt или .png, ...)

Вот воспроизводимый пример с очень маленькими данными, использующими наборы данных, включенные в R (mtcars и iris).

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)

Большое спасибо за вашу помощь и предложения!

1 Ответ

1 голос
/ 03 апреля 2020

Как отмечается в комментариях к связанному посту, обычно не рекомендуется менять рабочий каталог (и в этом случае нет необходимости). Несмотря на несущественность с небольшим количеством файлов, вызов paste0 для создания пути не обязательно должен быть в for l oop, поскольку он векторизован. Это также устраняет необходимость динамического увеличения вектора fs (что также обычно является плохой практикой). Наконец, моя утилита zip не была на моем пути, что привело к сбою utils::zip (вы можете указать путь в вызове функции, в противном случае она проверяет переменную окружения R_ZIPCMD и по умолчанию принимает значение zip, предполагая ее быть на пути).

Я в целом согласен с принятым ответом, но вот альтернативное решение, использующее вместо него функцию zip::zipr (также walk вместо for l oop)

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"
  )
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...