如何阻止Android Chrome自动重命名Shiny应用下载的同名文件?
解决Android Chrome下载Shiny应用文件自动重命名的问题
问题概述
我用R Shiny开发了一款安卓端日历应用,核心流程为:上传含DataFrame的日历文件→添加当日数据→保存更新后的文件,要求文件名始终保持为Horaires.RData以追踪每日数据。但Android Chrome会自动给重复文件名的下载文件添加后缀(如Horaires(1).RData、Horaires(2).RData),Linux端可通过浏览器扩展解决,但安卓端无类似安全开关,尝试Chromium也未解决。不考虑删除原文件的方案(风险较高),希望有类似Chrome扩展开关的安全解决方案。
可行解决方案
方案1:自定义HTTP响应头强制文件名(推荐)
Android Chrome的自动重命名源于浏览器检测到目标目录已有同名文件,我们可以通过设置Content-Disposition响应头明确指定文件名,同时添加X-Download-Options提示浏览器直接下载,部分安卓浏览器会尊重该设置。
修改后的Shiny代码如下(已修复原代码中场景数据长度不匹配的bug):
library(shiny) library(shinyTime) library(shinyFiles) ui <- fluidPage( titlePanel("Horaires Turbin :D"), fluidRow( div( fileInput("files", "File data", multiple=F), style="background-color:#ADD8E6;margin-right:2.5%;margin-left:2.5%;padding:2.5%;color:white;margin-bottom:2.5%" ), div( dateInput("date4", "Jour considéré", value = Sys.Date()), radioButtons("Situation", label = "Situation", choices = c("Boulot", "Vacances", "Lab"), selected = "Boulot"), uiOutput("moreControls"), textInput("Note", "Note", ""), style="background-color:#ADD8E6;margin-right:2.5%;margin-left:2.5%;padding:2.5%;color:white;margin-bottom:2.5%" ), div( h2("A sauvegarder :"), uiOutput("toSave"), style="background-color:#ADD8E6;margin-right:2.5%;margin-left:2.5%;padding:2.5%;color:white;margin-bottom:2.5%", ), div( downloadButton("downloadData", "Save"), style="background-color:#ADD8E6;margin-right:2.5%;margin-left:2.5%;padding:2.5%;color:white;margin-bottom:2.5%" ) ) ) server <- function(input, output, session) { calendrier <- reactiveValues(dat = NULL) dataToSave <- reactiveValues(dat = NULL) observe({ output$moreControls <- renderUI({ if(input$Situation == "Vacances"){ NULL }else if(input$Situation == "Lab"){ NULL } else if(input$Situation == "Boulot"){ div( timeInput("time1", "Matin", value = strptime("00:00:00", "%T")), timeInput("time2", "Midi", value = strptime("00:00:00", "%T")), timeInput("time3", "Aprem", value = strptime("00:00:00", "%T")), timeInput("time4", "Soir", value = strptime("00:00:00", "%T")) ) } }) output$toSave <- renderUI({ if(input$Situation == "Vacances"){ div("Vacances", p(input$Note)) }else if(input$Situation == "Lab"){ div("Lab", p(input$Note)) } else if(input$Situation == "Boulot"){ div( paste0("Jour concerné : ", strftime(input$date4, "%d-%m-%Y")), br(), paste0("Matin : ", strftime(input$time1, "%T")), br(), paste0("Midi : ", strftime(input$time2, "%T")), br(), paste0("Aprem : ", strftime(input$time3, "%T")), br(), paste0("Soir : ", strftime(input$time4, "%T")), br(), input$Note ) } }) }) observe({ if(!is.null(input$files$datapath)){ load(input$files$datapath) calendrier$dat <- ToSave } }) observe({ output$downloadData <- downloadHandler( filename = function() { "Horaires.RData" }, content = function(file) { # 适配不同场景的数据长度,避免rbind报错 if(input$Situation %in% c("Vacances", "Lab")){ data <- c(as.character(input$date4), "", "", "", "", as.character(input$Note)) } else { data <- c(as.character(input$date4), as.character(strftime(input$time1, "%T")), as.character(strftime(input$time2, "%T")), as.character(strftime(input$time3, "%T")), as.character(strftime(input$time4, "%T")), as.character(input$Note)) } ToSave <- rbind(calendrier$dat, data) save(ToSave, file = file) }, # 添加自定义HTTP头强制文件名 contentType = "application/octet-stream", headers = list( "Content-Disposition" = 'attachment; filename="Horaires.RData"; filename*=UTF-8''Horaires.RData', "X-Download-Options" = "noopen" ) ) }) } shinyApp(ui, server)
方案2:更换安卓浏览器
- Kiwi Browser:基于Chromium,支持安装Chrome扩展,可使用
Download Manager类扩展强制保持文件名 - Firefox for Android:在设置中关闭"自动重命名重复文件"选项,直接覆盖原文件
方案3:云端同步替代本地文件
将文件存储在云端,应用直接读取和更新云端文件,避免本地文件重命名问题。可使用googledrive包实现Shiny与云端的交互,无需用户手动下载/上传。
内容的提问来源于stack exchange,提问作者CharlotteS.
相关产品推荐
相关产品推荐

