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():
- 页面正常显示图表
- 点击下载按钮,会生成格式正确的PNG文件,文件名包含指定前缀、日期、宽高参数
- 文件可正常下载并打开,无错误提示
内容的提问来源于stack exchange,提问作者Victor Yuan
相关产品推荐
相关产品推荐

