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

能否在Shiny中显示从AWS S3下载文件的实时进度条?

实现Shiny中S3下载的实时进度显示

核心方案是用future+promises将S3下载任务放到后台线程,同时自定义进度回调来实时更新Shiny的UI状态,避免主UI线程被阻塞。

步骤1:依赖包准备

需要安装并加载以下包:

  • shiny
  • aws.s3
  • future
  • promises
  • progress(s3load内部依赖)

步骤2:UI部分设计

添加触发下载的按钮和实时进度展示组件(这里用shinydashboard进度条为例,也可替换为普通文本):

library(shiny)
library(shinydashboard)

ui <- dashboardPage(
  dashboardHeader(title = "S3下载进度演示"),
  dashboardSidebar(
    actionButton("start_download", "开始从S3下载")
  ),
  dashboardBody(
    box(
      title = "实时下载进度",
      status = "primary",
      solidHeader = TRUE,
      width = 6,
      progressBar("download_progress", value = 0, display_pct = TRUE)
    ),
    box(
      title = "下载状态",
      status = "info",
      solidHeader = TRUE,
      width = 6,
      textOutput("status_text")
    )
  )
)

步骤3:Server端核心逻辑

3.1 配置异步运行环境

在server函数开头设置future的运行计划,用多会话模式释放主UI线程:

server <- function(input, output, session) {
  # 配置future后台运行
  plan(multisession)
  
  # 存储进度、状态和下载数据的反应式值
  rv <- reactiveValues(
    progress = 0,
    download_status = "等待触发下载",
    data = NULL
  )

3.2 自定义进度回调

创建自定义进度条对象,重写其更新逻辑,将进度同步到反应式值:

# 自定义进度回调,绑定到Shiny反应式值
  create_progress_bar <- function() {
    pb <- progress::progress_bar$new(
      total = 100,
      clear = FALSE,
      show_after = 0
    )
    
    # 重写进度更新事件,同步到rv$progress
    pb$on_update <- function(value) {
      # value是0-1的比例,转换为百分比
      rv$progress <- round(value * 100)
      rv$download_status <- sprintf("正在下载: %d%%", rv$progress)
    }
    
    pb
  }

3.3 触发异步下载任务

用future包装s3load任务,通过promises的%...>%处理完成后的逻辑:

# 触发下载的事件
  observeEvent(input$start_download, {
    rv$progress <- 0
    rv$download_status <- "初始化下载任务..."
    
    # 创建自定义进度条
    pb <- create_progress_bar()
    
    # 异步执行S3下载
    future({
      # 替换为你的S3路径和参数
      s3load(
        object = "s3://your-bucket/path/to/your/file.rds",
        progress = pb,  # 使用自定义进度条
        # 其他s3load参数...
      )
    }) %...>% {
      # 下载成功后的处理
      rv$data <- .
      rv$download_status <- "下载完成!"
      showNotification("文件下载成功", type = "success")
    } %>% catch(function(err) {
      # 捕获错误并提示
      rv$download_status <- sprintf("下载失败: %s", err$message)
      showNotification(rv$download_status, type = "error")
    })
  })

3.4 实时更新UI组件

绑定反应式值到UI,自动更新进度条和状态文本:

# 更新进度条
  observe({
    updateProgressBar(session, "download_progress", value = rv$progress)
  })
  
  # 输出状态文本
  output$status_text <- renderText({
    rv$download_status
  })
}

关键细节说明

  1. 为什么用future?:Shiny主进程是单线程,直接调用s3load会阻塞UI,multisession模式将耗时任务放到独立后台进程,主线程可继续处理UI交互和更新。
  2. 自定义进度条的意义:s3load的with_progress=TRUE默认输出到控制台,我们通过重写on_update方法,把进度同步到Shiny反应式值,实现UI实时更新。
  3. promises的作用:处理异步任务的成功/失败回调,确保下载完成后能正确更新状态或处理数据。

完整运行

最后启动Shiny应用:

shinyApp(ui, server)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 09:48:24