Shiny downloadButton()和downloadHandler()500错误

时间:2017-02-16 19:03:21

标签: shiny shiny-server shinydashboard

我开发了一个Shiny Dashboard,我有几个数据框可以通过反应式文件阅读器等导入。我还添加了一个“Generate PDF”按钮,在我的ui.R代码中使用了downloadButton()。我的server.R代码实现downloadHandler()来处理该请求。

在我的Windows桌面上,这一切都很完美。我想让它在我设置的Linux服务器上运行。当然,我必须修改一些路径,Shiny Server在此框中以root身份运行。当我单击Linux服务器上运行的站点上的“生成PDF”按钮时,我几乎立即收到HTTP 500错误。我自己在Linux服务器上手动编译了pdfReport.Rmd文件,它运行得很好。

我猜两件事之一:

  1. 不知何故,数据在Linux机器上的传递方式与在Windows桌面上传递的方式不同。这可能不太可能,但这是可能的。
  2. 我的路径出了问题,所以当写入临时文件开始生成PDF时,系统没有能力或者没有路径来写文件。可能我的downloadHandler()代码在某种程度上是畸形的。我认为这比#1更有可能。
  3. 这是我的downloadHandler()代码:

    output$pdfReport <- downloadHandler(
      # For PDF output, change this to "report.pdf"
      filename = reactive({paste0("/srv/shiny-server/itpod/","ITPOD-",Sys.Date(),".pdf")}),
    
      content = function(file) {
        # Copy the report file to a temporary directory before processing it, in
        # case we don't have write permissions to the current working dir (which
        # can happen when deployed).
    
        tempReport <- file.path("/srv/shiny-server/itpod", "pdfReport.Rmd")
        file.copy("report.Rmd", tempReport, overwrite = TRUE)
    
        params <- list(ilp=updateILP(), ico=updateICO(), sec=updateSecurity(), ppwc=updateWorkPreviousPeriodCompleted(),
                       pow=updateOngoingWorkCABApproved(), pwcr=updatePlannedWorkCABRequested(), epca=updateEmergencyChangesPendingCABApproval(),
                       fac=updateFacilities(), drs=updateDRStatus(), ov=updateOperationalEvents(), sl=updateStaffLocations(),
                       w = updateWeather())
    
        # Knit the document, passing in the `params` list, and eval it in a
        # child of the global environment (this isolates the code in the document
        # from the code in this app).
        rmarkdown::render(tempReport, output_file = file, params = params, envir = new.env(parent = globalenv())
        )
      }
    )
    

    我想也许这条路径不可写,所以我尝试将其更改为/ tmp,但这也不起作用。我发现,当我点击“生成PDF”按钮时,我会得到一个带有“会话”的长URL:

    http://my.url.com:3838/itpod/session/d661a858f5679aba26692bc9b4442872/download/pdfReport?w=
    

    我开始怀疑这是否是问题,而且我不是在写当前会话的路径或其他什么?这是Shiny的一个新领域。就像我说的,在我的桌面上它工作正常,但是一旦我将它部署到Linux服务器,它就无法正常工作。任何帮助将非常感激。提前谢谢!

1 个答案:

答案 0 :(得分:0)

好的 - 经过多次故障排除后,我发现我在闪亮的webroot中拥有的一些文件是主pdfReport.Rmd文件的依赖项,因为代码将报告复制到temp 。目录

因为我不想将我的webroot中的所有文件复制到temp,所以我决定在webroot中自己渲染报表。对我来说,这并不是什么大不了的事,因为我的闪亮应用程序无论如何都以root身份运行。

我会解决这个问题,因为我已经解决了这个问题,基本上我的修复方法是执行以下操作:

  1. 使服务以普通用户身份运行
  2. 我不得不复制报告所依赖的文件,而是必须在报告代码中静态引用它们。
  3. 我为所有可能已经阅读并正在努力的人道歉。我的修复是上面的代码如下:

    output$pdfReport <- downloadHandler(
          # For PDF output, change this to "report.pdf"
          filename = reactive({paste0("/srv/shiny-server/itpod/","ITPOD-",Sys.Date(),".pdf")}),
    
          content = function(file) {
            # Copy the report file to a temporary directory before processing it, in
            # case we don't have write permissions to the current working dir (which
            # can happen when deployed).
    
            report <- file.path(getwd(), "pdfReport.Rmd")
            #tempReport <- file.path(tempdir(), "pdfReport.Rmd")
            #file.copy("pdfReport.Rmd", tempReport, overwrite = TRUE)
    
            params <- list(ilp=updateILP(), ico=updateICO(), sec=updateSecurity(), ppwc=updateWorkPreviousPeriodCompleted(),
                           pow=updateOngoingWorkCABApproved(), pwcr=updatePlannedWorkCABRequested(), epca=updateEmergencyChangesPendingCABApproval(),
                           fac=updateFacilities(), drs=updateDRStatus(), ov=updateOperationalEvents(), sl=updateStaffLocations(),
                           w = updateWeather())
    
            # Knit the document, passing in the `params` list, and eval it in a
            # child of the global environment (this isolates the code in the document
            # from the code in this app).
            rmarkdown::render(report, output_file = file, params = params, envir = new.env(parent = globalenv())
            )
          }
        )
    
      })
    

    请注意,我不是将文件复制到临时目录,而只是在当前工作目录中指定文件。