[英]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.x的JavaFileUpload
文档 ,听起来您以后不需要用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.