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

Shiny图表下载模块故障排查:文件名异常与下载失败

Shiny图表下载模块修复方案

问题描述

开发了一款可复用的Shiny图表下载模块,计划在应用多处调用,但模块无法正常运行。最小化测试应用中可预览图表,但点击下载按钮时,文件名渲染错误,且下载的是htm文件,提示“无法下载,无文件”。

错误原因分析

  • 临时文件路径错误:downloadHandler的content参数中,file是Shiny自动生成的临时文件路径,直接给它添加prefix会导致路径异常,ggsave无法正确输出文件,触发Shiny返回错误页面(即下载的htm文件)。
  • 依赖包缺失:代码使用stringr::str_glue生成文件名,但未加载stringr包,会导致文件名生成失败。
  • 格式未显式指定:ggsave虽能从文件名推断格式,但显式指定device参数可避免潜在的格式识别问题。
  • 前缀处理位置错误:文件名前缀应在filename函数中拼接,而非修改临时文件路径。

修复后的完整代码

library(shiny)
library(bs4Dash)
library(ggplot2)
library(stringr)  # 新增:加载依赖包stringr

#' download plot UI
#' @export
download_plot_UI <- function(id) {
  ns <- NS(id)
  tagList(
    bs4Dash::column(
      12,
      fluidRow(
        bs4Dash::column(
          width = 4,
          downloadButton(
            ns('download_plot'),'Download .png',
            width = '100%')
        ),
        bs4Dash::column(8)
      ),
      fluidRow(
        bs4Dash::column(
          width = 1,
          numericInput(
            ns('download_plot_width'), 'Width (in)',
            value = 7, step = 1, min = 1, max = 25),
        ),
        bs4Dash::column(
          width = 1,
          numericInput(
            ns('download_plot_height'), 'Height',
            value = 7, step = 1, min = 1, max = 25, width = '100%')
        ),
        bs4Dash::column(width = 9)
      )
    )
  )
}

#' download plot server
#' @export
#' @param gg ggplot2 object
#' @param prefix string prefix to add to filename
download_plot_server <- function(id, gg, prefix = '') {
  stopifnot(is.reactive(gg))
  moduleServer(
    id,
    function(input, output, session) {

      output$download_plot <- downloadHandler(
        filename = function() {
          # 修改:在filename函数中处理前缀,确保文件名格式正确
          stringr::str_glue(
            "{prefix}_{Sys.Date()}_",
            "w{input$download_plot_width}",
            "h{input$download_plot_height}",
            "_scdotplot.png"
          )
        },
        content = function(file) {
          message(stringr::str_glue(
            'Printing dotplot: {file} ',
            'Width: {input$download_plot_width} ',
            'Height: {input$download_plot_height}'
          ))
          # 修改:直接使用Shiny提供的临时文件路径file,显式指定device为png
          ggsave(
            plot = gg(),
            file = file,
            width = input$download_plot_width,
            height = input$download_plot_height,
            device = "png"
          )
        }
      )
    }
  )
}

#' @export
#' @examples \dontrun{
#'  download_plot_app()
#' }
download_plot_app <- function(...) {

  # ui----
  ui <- fluidPage(
    titlePanel("download_plot module"),
    shiny::plotOutput('ggplot'),
    download_plot_UI('download_plot')
  )

  server <- function(input, output, session) {

    p <- reactive(
      ggplot(mtcars, aes(mpg, cyl)) + geom_point()
    )
    output$ggplot <- renderPlot(p())
    download_plot_server(
      'download_plot',
      gg =  p
    )
  }
  shinyApp(ui, server, ...)
}

download_plot_app()

验证说明

运行修复后的download_plot_app():

  1. 页面正常显示图表
  2. 点击下载按钮,会生成格式正确的PNG文件,文件名包含指定前缀、日期、宽高参数
  3. 文件可正常下载并打开,无错误提示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 12:47:03