【问题标题】:Tempfiles when using shiny使用闪亮时的临时文件
【发布时间】:2018-04-23 10:54:29
【问题描述】:

我正在开发一个闪亮的应用程序,用户可以在其中上传文件并选择 X 参数,然后按下一个按钮,它会生成 5 个图(ggplot2 和 barplot)以及一个动态数据表(DT)。另外,我想把我闪亮的应用程序放到一个 linux 服务器中。

我使用tempfiles() 来创建用于创建绘图和DT 的每个文件。

之后,我的问题是:

当用户关闭闪亮的应用程序(关闭窗口)时,临时文件会自动删除吗?

如果没有,我该怎么做才能删除临时文件?

我的尝试:

session$onSessionEnded(function() {
  if (!is.null(x1)) {
    file.remove(x1)
  }
  if (!is.null(x2)) {
    file.remove(x2)
  }
  if (!is.null(x3)) {
    file.remove(x3)
  }
  if (!is.null(x4)) {
    file.remove(x4)
  }
  if (!is.null(xx)) {
    file.remove(xx)
  }
})

或者:

session$onSessionEnded(function() {
  files <- list.files(tempdir(), full.names = T, pattern = "^file")
  file.remove(files)
})

使用该代码,我在用户按下按钮一次时删除临时文件,如果用户按下按钮超过 1 次,则窗口关闭,它只会删除最后生成的文件。第二部分删除临时目录中的所有文件,但这会影响其他用户吗?(我认为是的,这就是我需要另一个解决方案的原因)。

ggplot 和 barplot 生成的 .png 临时文件不会自动删除。

我担心的是,如果临时文件不会自动删除,那么 linux 服务器会因为临时文件太多而崩溃。

希望你能解决我的疑惑。阿特琼。

【问题讨论】:

    标签: r shiny temporary-files


    【解决方案1】:

    如果您希望render 函数自动删除您的临时文件,您可以使用deleteFile=TRUE 参数:

    shinyServer(function(input, output, clientData) {
      output$myImage <- renderImage({
        # A temp file to save the output.
        # This file will be removed later by renderImage
        outfile <- tempfile(fileext='.png')
    
        # Generate the PNG
        png(outfile, width=400, height=300)
        hist(rnorm(input$obs), main="Generated in renderImage()")
        dev.off()
    
        # Return a list containing the filename
        list(src = outfile,
             contentType = 'image/png',
             width = 400,
             height = 300,
             alt = "This is alternate text")
          }, deleteFile = TRUE)
        })
    

    创建一个临时文件来保存输出,该文件稍后会因为deleteFile=TRUE 参数而被自动删除。

    默认的 Shiny (shiny.R) 也有一个内置机制,可以清除文件上传目录,如果您担心的话。以下代码在会话结束时删除上传目录:

    registerSessionEndCallbacks = function() {
          # This is to be called from the initialization. It registers functions
          # that are called when a session ends.
    
          # Clear file upload directories, if present
          self$onSessionEnded(private$fileUploadContext$rmUploadDirs)
        }
    

    关于手动删除临时文件的另一点(正如您尝试的那样):每次用户切换到另一个选项卡或调整他/她的浏览器窗口大小时,该图都必须呈现,所以如果您手动删除文件,它可能效率低下,因为它需要再次重新渲染。 onSessionEnded 解决方案更好,因为它确认会话已经结束。

    session$onSessionEnded(function() {
       if (!is.null(input$file1)) {
        file.remove(input$file1$datapath)
      }
    })
    

    【讨论】:

    • 如果我输入deleteFile = TRUE,文件会在用户关闭应用程序时或之前删除吗?另外我的想法是删除在用户会话期间创建的所有文件(我将拥有超过 5 个用户)。
    • 该变量用于指定文件在发送到客户端浏览器后是否应该被删除。所以它在renderImage()renderPlot() 执行后被删除。一般来说,如果图像是临时文件,那么这应该是 TRUE
    • 我评论的第二部分呢?请
    • Ahhhh 好的,现在您的顾虑更清楚了。您是否考虑过定期使用unlink(dir1, recursive = T) 删除整个目录?或者当您的临时文件的长度超过一定大小时,例如在list.files(tmp_dir, full.names = T, pattern = "^file") 上使用length
    • 我建议不要使用unlink——尤其是recursive=T——在闪亮的代码中,它似乎太“接近”而无法恶意地做事(我只是觉得不对劲) );即使这样的事情没有已知的“利用”,它似乎也有风险。 J0ki,通常临时目录在服务系统上有一个清理 cron 作业;如果没有,我建议您确保操作系统有一个像 find ${TMPDIR} -atime 24 -print0 | xargs -0 rm 这样的 cron 作业,每隔几个小时或每天运行一次,这将是一种更好/安全的方法。
    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 2018-11-14
    • 2019-04-08
    • 1970-01-01
    • 2015-08-09
    • 2016-10-24
    • 2019-01-26
    相关资源
    最近更新 更多