You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何阻止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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 12:02:34