Java 如何使用JAX-RS提供文件,然后将其删除?
我有一个使用JAX-RS的服务器应用程序。我正在向它添加一个端点,它将从S3 bucket中检索一个对象(也就是一个文件),将其保存在一个临时文件夹中,提供这个文件,然后将其从临时文件夹中删除。因此,我要添加的其中一种方法如下所示:Java 如何使用JAX-RS提供文件,然后将其删除?,java,file,jax-rs,java-io,temporary-files,Java,File,Jax Rs,Java Io,Temporary Files,我有一个使用JAX-RS的服务器应用程序。我正在向它添加一个端点,它将从S3 bucket中检索一个对象(也就是一个文件),将其保存在一个临时文件夹中,提供这个文件,然后将其从临时文件夹中删除。因此,我要添加的其中一种方法如下所示: @GET @Path("/download-file") public Response downloadFile() { File tempFile = null; try { tempFile = s3FileDownloade
@GET
@Path("/download-file")
public Response downloadFile() {
File tempFile = null;
try {
tempFile = s3FileDownloader.downloadFile();
Response response = Response.ok(tempFile)
.header("Content-Disposition", "attachment; filename=myfile.dat")
.header("Content-Type", "application/octet-stream")
.build();
return response;
} finally {
if (tempFile != null) {
tempFile.delete();
}
}
}
但是,这不起作用,因为它似乎在渲染文件之前执行finally块中的delete()
方法。当我到达端点时,Tomcat发出一个500错误,说明“系统找不到指定的文件”
如果我将其更改为tempFile.deleteOnExit()
,则它可以工作。然而,这并不理想,因为服务器永远不会真正退出,除了在很少发生的重新启动时。如何让它在输出到达delete语句之前呈现输出?还是有更好的办法
更新:根据请求,在下面添加我的FileDownloader类的代码
public class FileDownloader {
private final AmazonS3Client s3Client;
private final String bucketName;
public FileDownloader(AmazonS3Client s3Client, String bucketName) {
this.s3Client = s3Client;
this.bucketName = bucketName;
}
public File downloadFile(String key) {
InputStream inputStream = null;
OutputStream outputStream = null;
try {
S3Object data = s3Client.getObject(bucketName, key);
inputStream = data.getObjectContent();
File file = File.createTempFile(System.getProperty("java.io.tmpdr"), "." + FileNameUtils.getExtension(key));
outputStream = new FileOutputStream(file);
int read;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, read);
}
return file;
} catch (AmazonS3Exception|IOException ex) {
// log the exception
// throw a custom exception type instead
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException) { }
try {
if (outputStream != null) {
outputStream.close();
}
} catch (IOException ex) { }
}
}
}
我非常怀疑Jax-RS或任何原始的基于Servlet的框架是否会让您通过提供一个file对象将文件发送给客户机。我认为您需要在tempFile.delete()之前获取该文件对象,将其转换为某种流,获取响应流,并通过您自己流式传输位。如果你有一个实际的临时文件,你也不需要删除它,我相信JVM会在ExitPerhaps上删除,用getLength()或getStatus()检查响应程序,然后用If删除。上面的评论也将被推荐。文件有多大?你能发布S3FileDownloader的文档吗?因为将下载的内容存储到文件中看起来毫无用处,如果您仍要删除该文件。@jbnize不确定,我已经添加了代码。您是否建议我直接将InputStream传递到JAX-RS,而不是将其保存到文件中?文件的大小也会有所不同;有些可能很小,但有些可能相当大(即20+MB)。是的,AFAIK(就我对规范的理解而言),您可以直接将InputStream传递给ok()。我非常怀疑Jax RS或任何原始的基于Servlet的框架是否会让您通过提供一个file对象将文件发送给客户端。我认为您需要在tempFile.delete()之前获取该文件对象,将其转换为某种流,获取响应流,并通过您自己流式传输位。如果你有一个实际的临时文件,你也不需要删除它,我相信JVM会在ExitPerhaps上删除,用getLength()或getStatus()检查响应程序,然后用If删除。上面的评论也将被推荐。文件有多大?你能发布S3FileDownloader的文档吗?因为将下载的内容存储到文件中看起来毫无用处,如果您仍要删除该文件。@jbnize不确定,我已经添加了代码。您是否建议我直接将InputStream传递到JAX-RS,而不是将其保存到文件中?文件的大小也会有所不同;有些可能很小,但有些可能相当大(即20+MB)。是的,在AFAIK(就我所了解的规范而言),您可以直接将InputStream传递给ok()。