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

R Shiny应用误判内容相同文件名不同的CSV为同一文件的问题

问题根源

Shiny 的fileInput组件默认会根据文件内容的哈希值判断响应值是否变化。当上传文件名不同但内容完全一致的文件时,input$file1/input$file2不会被标记为新的响应变化,导致关联的重置逻辑(清空状态、禁用下载按钮)不触发;同时如果之前的处理结果仍保留,会让用户误以为应用未重新执行处理流程。

解决方法

方法1:监听文件名变化(推荐)

修改文件选择的监听逻辑,改为监听文件名而非整个文件对象,确保只要文件名变化就触发重置,同时清空之前的处理结果,强制点击PROCESS按钮时重新执行处理:

# 修改第一个tab的文件选择监听逻辑
observeEvent(input$file1$name, {
    output$ready1 <- renderText("")
    shinyjs::removeClass("download1", "button_color")
    shinyjs::disable("download1")
    result_f1(NULL)  # 重置之前的处理结果
  }, ignoreNULL = FALSE)

# 修改第二个tab的文件选择监听逻辑
observeEvent(input$file2$name, {
    output$ready2 <- renderText("")
    shinyjs::removeClass("download2", "button_color")
    shinyjs::disable("download2")
    result_f2(NULL)  # 重置之前的处理结果
  }, ignoreNULL = FALSE)

方法2:强制重置fileInput组件状态

使用shinyjs的reset函数,强制重置fileInput的状态,确保每次文件选择都被视为新操作:

# 修改第一个tab的文件选择监听逻辑
observeEvent(input$file1, {
    invalidateLater(100)  # 延迟确保文件上传完成
    shinyjs::reset("file1")
    output$ready1 <- renderText("")
    shinyjs::removeClass("download1", "button_color")
    shinyjs::disable("download1")
    result_f1(NULL)
  }, ignoreNULL = FALSE)

# 修改第二个tab的文件选择监听逻辑
observeEvent(input$file2, {
    invalidateLater(100)
    shinyjs::reset("file2")
    output$ready2 <- renderText("")
    shinyjs::removeClass("download2", "button_color")
    shinyjs::disable("download2")
    result_f2(NULL)
  }, ignoreNULL = FALSE)
完整修改后的代码
library(shiny)
library(shinyjs)
library(RMySQL)
library(tidyverse)
library(lubridate)
library(rio)

ui <- fluidPage(
  useShinyjs(),
  tags$head(
    tags$style(
      HTML(
        "
        .button_color {
        background-color: #89CFF0;
        border-color: white;
        }
        "
          )
            )
         ),
  
  tabsetPanel(type = "tabs",
  
  tabPanel("FIRST PURCHASE",
  fileInput("file1", "Choose CSV file ", accept = ".csv"),
  actionButton("process1", "PROCESS"),
  downloadButton("download1", "Download Processed CSV", style = "color: grey;"),
  textOutput("ready1")),
  
  
  tabPanel("COUPON INFO",
  fileInput("file2", "Choose CSV file ", accept = ".csv"),
  actionButton("process2", "PROCESS"),
  downloadButton("download2", "Download Processed CSV", style = "color: grey;"),
  textOutput("ready2"))
  )
  
)

server <- function(input, output, session) {
  result_f1 <- reactiveVal(NULL)
  result_f2 <- reactiveVal(NULL)
  
  
  observeEvent(input$process1, {
    req(input$file1)
    
    result1 <- tryCatch({
      ### Database Connection & Tables Connection -------------------
      api_backend <- dbConnect(
        MySQL(),
        dbname = "api_backend",
        user = "readonly_user",
        password = "password123",
        host = "fundednext-production.cqtlpb5sm2vt.ap-northeast-1.rds.amazonaws.com",
        port = 3306
      )
      
      # Input Email list
      email_list <- read.csv(input$file1$datapath) %>% 
        filter(email != "") %>% 
        mutate(email = str_trim(tolower(email)))
      
      # Find customers that are present in the email list
      customers_df <- tbl(api_backend, "customers") %>% 
        filter(email %in% !!email_list$email) %>% 
        collect()
      
      # Find accounts needed (doing this to make the code faster)
      accounts_df <- tbl(api_backend, "accounts") %>% 
        filter(customer_id %in% !!customers_df$id) %>% 
        collect()
      
      # Find only the necessary orders
      orders_df <- tbl(api_backend, "orders") %>% 
        filter(account_id %in% !!accounts_df$id) %>% 
        collect()
      
      coupons_df <- collect(tbl(api_backend, "coupons"))
      
      orders_df_first_order <- orders_df %>% 
        filter(status == 1) %>% 
        distinct(customer_id, .keep_all = T)
      
      email_list %>% 
        left_join(
          select(customers_df, email, customer_id = id)
        ) %>% 
        left_join(
          select(orders_df_first_order, customer_id, purchase_date = created_at, coupon_id, price = grand_total)
        ) %>% 
        left_join(
          select(coupons_df, coupon_id = id, coupon_code = code)
        ) %>% 
        select(email, affiliate, price, purchase_date, coupon_code)
      
    }, error = function(e) {
      return(paste(
        "Some error happen!",
        "Error message:",
        e,
        sep = "\n"
      ))
    }, finally = {
      lapply(dbListConnections(MySQL()), dbDisconnect)
    })
    
 #forcing result to be a data frame
    result_f1(as.data.frame(result1))
  })
  
  #2nd tab
  
  
  observeEvent(input$process2, {
    req(input$file2)
    
  result2 <- tryCatch({
    ### Database Connection & Tables Connection -------------------
    api_backend <- dbConnect(
      MySQL(),
      dbname = "api_backend",
      user = "readonly_user",
      password = "password123",
      host = "fundednext-production.cqtlpb5sm2vt.ap-northeast-1.rds.amazonaws.com",
      port = 3306
    )
    
    # Input Coupon list
    coupon_list <- read.csv(input$file2$datapath) %>% 
      filter(coupon != "") %>% 
      mutate(coupon = str_trim(coupon))
    
    # Find coupon ids
    coupons_df <- tbl(api_backend, "coupons") %>% 
      filter(code %in% !!coupon_list$coupon) %>% 
      select(coupon_id=id, coupon = code) %>% 
      collect()
    
    # Orders df filter 
    orders_df <- tbl(api_backend, "orders") %>% 
      filter(coupon_id %in% !!coupons_df$coupon_id) %>% 
      collect()
    
    # Find customers that are present in the orders
    customers_df <- tbl(api_backend, "customers") %>% 
      filter(id %in% !!orders_df$customer_id) %>% 
      collect()
    
    result_df <- orders_df %>% 
      filter(status == 1) %>% 
      group_by(customer_id) %>% 
      mutate(purchase_number = row_number()) %>% 
      mutate(first_purchase = case_when(
        purchase_number == 1 ~ "Yes", T ~ "No"
      )) %>% 
      ungroup() %>% 
      left_join(select(customers_df, customer_id=id, email)) %>% 
      left_join(coupons_df) %>% 
      select(coupon, revenue = grand_total, email, purchase_date = created_at, first_purchase)
    

  }, error = function(e) {
    return(paste(
      "Some error happen!",
      "Error message:",
      e,
      sep = "\n"
    ))
  }, finally = {
    lapply(dbListConnections(MySQL()), dbDisconnect)
  })
  
  #forcing result to be a data frame
  
  
  result_f2(as.data.frame(result2))
  
  })
  
  
  
  
  
  observe({ shinyjs:: disable('download1') })
  
  
  observe({ shinyjs:: disable('download2') })
  

  
  
  
  # 修改后的第一个tab文件选择监听
  observeEvent(input$file1$name, {
    output$ready1 <- renderText("")
    shinyjs::removeClass("download1", "button_color")
    shinyjs::disable("download1")
    result_f1(NULL)
  }, ignoreNULL = FALSE)
  
  
  
  # 修改后的第二个tab文件选择监听
  observeEvent(input$file2$name, {
    output$ready2 <- renderText("")
    shinyjs::removeClass("download2", "button_color")
    shinyjs::disable("download2")
    result_f2(NULL)
  }, ignoreNULL = FALSE)
  
  
  
  observe({
    shinyjs::toggleClass("download1", "button_color", condition = (class(result_f1()) == "data.frame"))
    
    if (class(result_f1()) == "character") {
      output$ready1 <- renderText({
        shinyjs::disable("download1")
        "There is an issue."
      })
    } else if (class(result_f1()) == "data.frame") {
      output$ready1 <- renderText({
        "The file is ready for download."
      })
      shinyjs::enable("download1") 
    }
  })
  
  

  observe({
    shinyjs::toggleClass("download2", "button_color", condition = (class(result_f2()) == "data.frame"))
    
    if (class(result_f2()) == "character") {
      output$ready2 <- renderText({
        shinyjs::disable("download2")
        "There is an issue."
      })
    } else if (class(result_f2()) == "data.frame") {
      output$ready2 <- renderText({
        "The file is ready for download."
      })
      shinyjs::enable("download2") 
    }
  })
  
  
  
  
  
  
  
  output$download1 <- downloadHandler(
    filename = function() {
      paste("req_file1", ".csv", sep = "")
    },
    content = function(file) {
      write.csv(result_f1(), file, row.names = FALSE)
    }
  )
  
  
  
  output$download2 <- downloadHandler(
    filename = function() {
      paste("req_file2", ".csv", sep = "")
    },
    content = function(file) {
      write.csv(result_f2(), file, row.names = FALSE)
    }
  )
  
  
  
}

shinyApp(ui = ui, server = server)

内容的提问来源于stack exchange,提问作者RockMachine98

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 01:34:51