简而言之: 如果直接在服务器函数内部使用 downloadHandler,则下载将按预期进行;但如果我以模块化方式在单独的脚本中使用 downloadHandler (在 moduleServer 内),那么当我下载文件时,它第一次可以工作,但如果我更新表并尝试下载新表,新下载的文件仍然包含第一个表的信息。因此,一旦我第一次下载数据,无论我之后在应用程序中进行哪种过滤或分组,当我尝试下载“新”表时,它总是会下载相同的原始下载表。
PD:这不仅适用于 .xlsx 文件,也适用于使用 write.csv() 的 .csv 文件
详细: 在构建闪亮的应用程序时,我总是采用模块方法,但在构建 downloadHandler 模块时我已经遇到问题一段时间了。对于这个模块,我有一个独立的脚本,具有以下功能:
download_button_UI <- function(id, label = "", class = "btn-primary btn-xs", ...) {
ns <- NS(id)
downloadButton(ns("down_button"),
label = label,
icon = icon("download"),
class = class,
title = "Download",
...)
}
download_button_Server <- function(id, df, name, ...) {
require(openxlsx)
moduleServer(id,
function(input, output, session) {
output$down_button <- downloadHandler(
filename = function() name,
# content = function(file) fwrite(df, file)
content = function(file) openxlsx::write.xlsx(df, file)
)
}
)
}
然后我分别在UI和Server中使用它:
# its a dashboardPage so the UI is in the "body" part of the page
body <- dashboardBody(
# some body parts
# Analysis table output
download_button_UI("down_analysis", "")
# some more body parts
)
server <- function(input, output, session) {
# some code
download_button_Server(id = "down_analysis", df = analysis_tbl()$df, name = "analysis.xlsx")
# some more code
}
第一次下载数据时,这按预期工作;但如果我更改数据的过滤器和分组/聚合并尝试下载“新”更新表,则生成的 .xlsx 文件仍包含第一个下载表的信息。
如果我直接在服务器函数中使用 downloadHandler,那么就没有问题,并且会下载最后更新的表:
# its a dashboardPage so the UI is in the "body" part of the page
body <- dashboardBody(
# some body parts
# Analysis table output
downloadButton("down_analysis", "")
# some more body parts
)
server <- function(input, output, session) {
# some code
output$down_analysis <- downloadHandler(
filename = "analysis.xlsx",
content = function(file) write.xlsx(summ_tbl()$df, file)
)
# some more code
}
然后代码按预期工作。
当然你可能会说,那么我应该只在服务器内部使用 downloadHandler 但我在应用程序中有几个表格和下载按钮,所以我不想一遍又一遍地重复相同的代码,模块解决方案很简单总是更好、更干净。
我不知道这是否是一个闪亮的错误,以及其他人是否遇到过类似的问题;我没有在任何其他网站上找到这个问题,正如我所说,我几年前就遇到过这个问题,而且它仍然存在,所以我想一劳永逸地解决它。
提前致谢!
您已通过
analysis_tbl()$df
将值传递到服务器模块,这意味着不会注册任何更新。您可能想要传递整个无功值analysis_tbl
。然后调用 analysis_tbl()
应始终给出最新值(请参见,这个答案)。
您的模块服务器可能如下所示:
# passing analysis_tbl reactive instead of df itself
download_button_Server <- function(id, analysis_tbl, name, ...) {
require(openxlsx)
moduleServer(id,
function(input, output, session) {
df <- analysis_tbl()$df
output$down_button <- downloadHandler(
filename = function() name,
content = function(file) openxlsx::write.xlsx(df, file)
)
}
)
}
对于您的应用程序:
server <- function(input, output, session) {
# some code
output$down_analysis <- downloadHandler(
filename = "analysis.xlsx",
content = function(file) write.xlsx(summ_tbl, file)
)
# some more code
}