繁体   English   中英

在Play框架中通过HTTP服务后删除文件-Java

[英]delete file after serving over HTTP in play framework - java

通过http提供文件后,如何删除文件,

        Files.TemporaryFile file = null;
        try {
          file = new Files.TemporaryFile(f);

            return ok().sendFile(file.file());
        } catch (IllegalArgumentException e) {
            return badRequest(Json.newObject().put("message", e.getMessage()));
        } finally {
           file.clean();
        }

使用此代码,文件将在投放之前被删除。 我在客户端上收到一个空文件。

通过阅读2.6.xJavaFileUpload文档 ,听起来您以后不需要用finally块来清理文件。 由于您使用的是TemporaryFile ,垃圾回收应注意删除资源:

... TemporaryFile背后的想法是,它仅在完成时处于作用域内,应尽快移出临时文件系统。 任何未移动的临时文件都将被[垃圾收集器]删除。

同一部分继续描述该文件有可能不会被垃圾回收导致拒绝服务问题。 如果发现文件没有被删除,则可以使用TemporaryFilesReaper

但是,在某些情况下,垃圾收集不会及时进行。 因此,还有一个play.api.libs.Files.TemporaryFileReaper ,可以使用Akka调度程序按计划删除临时文件,这与垃圾回收方法不同。

我并没有强制执行所有项目,但是可以仅将Scala用于此控制器,然后可以使用sendFile方法的onClose参数。 唯一需要注意的是-该参数并非在所有版本中都适用,在2.5中似乎存在问题,因此未触发(无效: https : //github.com/playframework/playframework/issues/6351 )。

另一种方式-您可以使用Akka流,例如: https : //www.playframework.com/documentation/2.6.x/JavaStream#Chunked-responses

2.8版中的Play框架在Java中也应该在sendFile方法中支持onClose参数(到目前为止,似乎仅在Scala版本中受支持)。

在较早的版本中(我仅在2.7.x上尝试过),您可以应用与2.8版修复中相同的方法,因此:

public Result doSomething() {
    final File fileToReturn = ....;
    final Source<ByteString, CompletionStage<IOResult>> source = FileIO.fromFile(fileToReturn);

    return Results.ok().streamed(wrap(source, () -> fileToReturn.delete()), Optional.of(fileToReturn.length()), Optional.of("content type, e.g. application/zip"));
}

private Source<ByteString, CompletionStage<IOResult>> wrap(final Source<ByteString, CompletionStage<IOResult>> source, final Runnable handler) {
    return source.mapMaterializedValue(
            action -> action.whenCompleteAsync((ioResult, exception) -> handler.run())
        );
} 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM