如何在Shiny的downloadHandler中使用响应式元素作为下载文件名
问题原因
你拿到的乱码临时文件名是因为错误使用了input$importedFile$datapath字段拼接导出文件名:
datapath是Shiny为上传文件生成的服务器本地临时存储路径,自带随机生成的目录、文件名前缀,用于避免重名冲突,本身就不是用户上传的原始文件名- 用户上传的原始文件名存储在
input$importedFile$name字段,需要用该字段拼接自定义后缀
核心改动说明
- 移除不必要的临时文件重命名操作,直接读取
datapath即可拿到上传的CSV文件内容 - 改用
name字段拼接导出文件名,使用R基础自带的tools::file_path_sans_ext()提取无后缀的原始文件名,再拼接_mod.csv,避免出现.csv_mod.csv的后缀嵌套问题 - 新增
write.csv的row.names = FALSE参数,避免导出文件多生成一列无用行号 - 原有业务逻辑保持不变:上传CSV新增一列后导出,文件名与用户上传的原文件对应
修正后完整可运行代码
ui <- fluidPage ( helpText("Click here to upload file"), fileInput(inputId = "importedFile", label = NULL, accept = c(".csv"), buttonLabel = "Upload File", placeholder = "NA"), helpText("Click here to download output"), downloadButton(outputId = "exportedOutput", label = "Download Output")) server <- function(input, output) { fileInfoFn <- reactive ( { inFile <- input$importedFile if (is.null(inFile)) { return(NULL) } fileInfo <- list( # 用原始文件名拼接后缀 outFile = paste0(tools::file_path_sans_ext(inFile$name), "_mod.csv"), # 直接读取临时路径的文件即可 fileData = read.csv(inFile$datapath) ) return(fileInfo) } ) produceOutput <- reactive( { fileInfo <- fileInfoFn() if (length(fileInfo) > 0){ dat4 <- fileInfo[["fileData"]] dat4$newColumn <- 1 } else { dat4 <- data.frame(x = "noData") } return(dat4) } ) output$exportedOutput <- downloadHandler( filename = function() { fileInfo <- fileInfoFn() if ("outFile" %in% names(fileInfo)) { outFile <- fileInfo[["outFile"]] } else { outFile <- "default.csv" } return(outFile) }, content = function(file){ write.csv(produceOutput(), file, row.names = FALSE) } ) } shinyApp(ui = ui, server = server)
内容的提问来源于stack exchange,提问作者K2Omland
相关产品推荐
相关产品推荐

