部署在shinyapps.io的Shiny App能否调用客户端Fiji并回传结果?
问题:部署Shiny App到shinyapps.io后,如何调用客户端本地Fiji并回传分析结果?
我搭建了一款本地运行正常的Shiny App,可通过以下代码自动启动ImageJ Fiji应用、执行宏代码分析图像并将结果回传至Shiny App:
Path0 <- "C:/Users/Username/Fiji.app/ImageJ-win64.exe --ij2 --run C:/Users/Username/Fiji.app/macros/TestingShiny.ijm" system(Path0)
现计划将该App部署至shinyapps.io,让用户无需下载R即可完成全流程分析(预计用户仍需本地安装Fiji)。但部署后,原文件路径与system调用无法正常工作。
简化版测试App代码如下:
## Load Packages pacman::p_load(pacman, rmarkdown, shiny, shinydashboard, shinyWidgets, fresh, here, tinytex, htmlwidgets) # Create the theme Theme <- create_theme( adminlte_color( red = "#FF4719" ), adminlte_sidebar( dark_bg = "#293745", dark_hover_bg = "#3CAAFF", ) ) ## Assign File Paths Path0 <- "C:/Users/Username/Fiji.app/ImageJ-win64.exe --ij2 --run C:/Users/Username/Fiji.app/macros/TestingShiny.ijm" ui <- dashboardPage(skin = "red", dashboardHeader( title = h4(HTML("Test"))), dashboardSidebar( sidebarMenu(id = "sidebarid", menuItem("Test Run", tabName = "info"))), dashboardBody( use_theme(Theme), tabItems( tabItem(tabName = "info", fluidRow( column( width = 4, fluidRow( actionBttn(inputId = "go", label = "Go!"), tableOutput(outputId = "text")) ) ))))) server <- function(input, output, session) { ## Sets observeEvent with eventReactive for Go button click observeEvent(input$go, { ## Runs Fiji and accompanying macro system(Path0) ## Pulls Result file from Output folder Result <- eventReactive(input$go, {read.delim(Path1)}) Filepath1 <- here("Output", "Log.txt") write.csv(Result(), Filepath1 , row.names = FALSE) ## Displays the result output$text <- renderTable(align = 'c', {Result()}) })} shinyApp(ui, server)
请问是否可以传递客户端本地的Fiji应用及宏文件路径,使Fiji在客户端运行并将结果回传至Shiny App?shinyFiles或shiny::fileInput()是否可行?
解决方案
核心结论
可以实现让客户端运行本地Fiji并回传结果,但要注意:部署在shinyapps.io的Shiny App,服务器端代码运行在云端,无法直接调用客户端本地程序或访问本地文件路径,必须调整为「客户端主动触发操作+结果上传」的模式。以下是两种可行方案:
方案1:用fileInput()实现结果回传(简单易实现,适合web部署)
此方案通过引导用户手动完成Fiji操作,再上传结果,无需复杂配置:
- 让用户上传待分析图像(如果宏需要处理特定图像):
fileInput("image_upload", "上传待分析图像", accept = c("image/tiff", "image/png", "image/jpeg")) - 提供宏文件下载:将你的
TestingShiny.ijm放在App的www目录,让用户下载到本地:
服务器端对应逻辑:downloadButton("download_macro", "下载分析宏文件")output$download_macro <- downloadHandler( filename = function() { "TestingShiny.ijm" }, content = function(file) { file.copy("www/TestingShiny.ijm", file) } ) - 引导用户运行Fiji:在UI中添加提示文本,告知用户打开本地Fiji,加载下载的宏和上传的图像,执行分析后导出结果文件(如
.txt或.csv)。 - 让用户上传结果文件:
fileInput("result_upload", "上传分析结果", accept = c(".txt", ".csv")) - 服务器端读取并展示结果:
observeEvent(input$result_upload, { result_df <- read.delim(input$result_upload$datapath) output$text <- renderTable(result_df, align = 'c') })
方案2:用shinyFiles获取本地路径(进阶,适合桌面打包)
shinyFiles可以让用户选择本地Fiji和宏文件的路径,但服务器端无法直接调用客户端程序,需借助额外工具触发:
- 安装并加载
shinyFiles:pacman::p_load(shinyFiles) - UI中添加路径选择组件:
shinyFilesButton("fiji_exe", "选择Fiji可执行文件", "选择ImageJ-win64.exe", multiple = FALSE) shinyFilesButton("macro_file", "选择宏文件", "选择TestingShiny.ijm", multiple = FALSE) - 服务器端获取路径并生成命令:
observe({ volumes <- getVolumes() shinyFileChoose(input, "fiji_exe", roots = volumes, session = session) shinyFileChoose(input, "macro_file", roots = volumes, session = session) if (!is.null(input$fiji_exe) && !is.null(input$macro_file)) { fiji_path <- parseFilePaths(volumes, input$fiji_exe)$datapath macro_path <- parseFilePaths(volumes, input$macro_file)$datapath # 生成可在本地执行的命令 run_cmd <- paste0('"', fiji_path, '" --ij2 --run "', macro_path, '"') # 将命令传递给客户端提示用户执行 session$sendCustomMessage(type = "showCmd", message = run_cmd) } }) - 客户端提示用户复制命令执行:在UI中添加JavaScript,接收服务器传递的命令并展示:
tags$script(' Shiny.addCustomMessageHandler("showCmd", function(cmd) { alert("请复制以下命令在本地CMD中执行:\\n" + cmd); }); ')注意:普通浏览器出于安全限制,无法直接通过JavaScript调用本地程序。如果要完全自动化触发,建议将Shiny App用
shinyElectron打包成桌面应用,可直接调用本地命令。
关键注意事项
- 部署在shinyapps.io的App,所有
system()或processx::run()调用都是在云端服务器执行,完全无法访问用户本地资源,必须放弃「服务器主动调用客户端程序」的思路。 - 如果追求全自动化体验,不适合部署在web端,更适合打包成桌面Shiny App。
内容的提问来源于stack exchange,提问作者MBS
相关产品推荐
相关产品推荐

