Ввод интерактивного каталога в приложении Shiny(R)




directory shiny-server (2)

Вы пробовали с пакетом shinyFiles ? Есть виджет, который позволяет вам выбрать каталог. В качестве вывода вы получите путь к этому каталогу, который вы в свою очередь можете использовать для доступа к файлам. Вот пример, как это работает.

сервер

library(shiny)
library(shinyFiles)

shinyServer(function(input, output, session) {

  # dir
  shinyDirChoose(input, 'dir', roots = c(home = '~'), filetypes = c('', 'txt'))
  dir <- reactive(input$dir)
  output$dir <- renderPrint(dir())

  # path
  path <- reactive({
    home <- normalizePath("~")
    file.path(home, paste(unlist(dir()$path[-1]), collapse = .Platform$file.sep))
  })

  # files
  output$files <- renderPrint(list.files(path()))
}) 

щ

library(shiny)
library(shinyFiles)

shinyUI(fluidPage(sidebarLayout(

  sidebarPanel(
    shinyDirButton("dir", "Chose directory", "Upload")
  ),

  mainPanel(
    h4("output$dir"),
    verbatimTextOutput("dir"), br(),
    h4("Files in that dir"),
    verbatimTextOutput("files")
  )

))) 

Надеюсь это поможет.

Я создаю блестящее приложение, которое требует от пользователя выбрать папку на локальном компьютере, которая содержит файлы, которые должны быть обработаны приложением.

Я использую решение, предложенное here . Это прекрасно работает на локальной машине, но не работает, если приложение развернуто на сервере shinyapps. Автор этого решения подтвердил, что оно предназначено только для работы с локальными приложениями Shiny, так как оно выполняет вызовы оболочки ОС для отображения диалогового окна каталога.

Мне интересно, есть ли другое диалоговое окно для каталогов, которое будет работать на развернутых приложениях Shiny (я развертываю на shinyapps.io).

Отредактировано: обратите внимание, что я не могу использовать интерфейс fileInput по двум причинам:

  1. Пользователи приложения не являются техническими специалистами, и они не знают, какие файлы в папке используются приложением.
  2. Выбранная папка может содержать другие папки, в которых находятся необходимые файлы, так что невозможно выбрать все файлы одновременно, даже если в интерфейсе fileInput включена опция multiple доступа.

Я не могу изменить структуру папок / файлов, она загружается как есть с медицинского устройства, и поэтому единственное, что я могу ожидать от пользователей, это указать родительскую папку, а все остальное должно быть сделано внутри кода R.


Это рабочий пример, основанный на использовании атрибута "webkitdirectory". На данный момент этот атрибут поддерживается в Chrome, Opera и Safari (для мобильных и настольных компьютеров), и его следует поддерживать в Firefox 49, который будет выпущен в сентябре. Подробнее об этом here . Он также работает с подкаталогами.

Требуется использование ключевого слова tags в ui.R. Я проверил это, загрузив три CSV-файла, каждый из которых содержит три числа, разделенных комой. Протестировано локально и на shinyapps.io с Chrome и Opera. Это код:

ui.R

    library(shiny)
    library(DT)

    shinyUI(tagList(fluidPage(theme = "bootstrap.css",
                      includeScript("./www/text.js"),
                      titlePanel("Folder content upload"),

                      fluidRow(
                              column(4,
                                     wellPanel(
                                             tags$div(class="form-group shiny-input-container", 
                                                      tags$div(tags$label("File input")),
                                                      tags$div(tags$label("Choose folder", class="btn btn-primary",
                                                                          tags$input(id = "fileIn", webkitdirectory = TRUE, type = "file", style="display: none;", onchange="pressed()"))),
                                                      tags$label("No folder choosen", id = "noFile"),
                                                      tags$div(id="fileIn_progress", class="progress progress-striped active shiny-file-input-progress",
                                                               tags$div(class="progress-bar")
                                                      )     
                                             ),
                                             verbatimTextOutput("results")
                                     )
                              ),
                              column(8,
                                     tabsetPanel(
                                             tabPanel("Files table", dataTableOutput("tbl")),
                                             tabPanel("Files list", dataTableOutput("tbl2"))
                                     )
                              )
                      )
    ),
    HTML("<script type='text/javascript' src='getFolders.js'></script>")
    )

    )          

server.R

    library(shiny)
    library(ggplot2)
    library(DT)

    shinyServer(function(input, output, session) {
            df <- reactive({
                    inFiles <- input$fileIn
                    df <- data.frame()
                    if (is.null(inFiles))
                            return(NULL)
                    for (i in seq_along(inFiles$datapath)) {
                            tmp <- read.csv(inFiles$datapath[i], header = FALSE)  
                            df <- rbind(df, tmp)
                    }
                    df

            })
            output$tbl <- DT::renderDataTable(
                    df()
            )
            output$tbl2 <- DT::renderDataTable(
                    input$fileIn
            )
            output$results = renderPrint({
                    input$mydata
            })

    })

text.js

window.pressed = function(){
        var a = document.getElementById('fileIn');
        if(a.value === "")
        {
            noFile.innerHTML = "No folder choosen";
        }
        else
        {
            noFile.innerHTML = "";
        }
    };

getFolders.js

     document.getElementById("fileIn").addEventListener("change", function(e) {

            let files = e.target.files;
            var arr = new Array(files.length*2);
            for (let i=0; i<files.length; i++) {

            //console.log(files[i].webkitRelativePath);
            //console.log(files[i].name);
            arr[i] = files[i].webkitRelativePath;
            arr[i+files.length] = files[i].name;


            }

            Shiny.onInputChange("mydata", arr);

    });

Позвольте мне знать, если это помогает.





shiny-server