我有一个使用JAX-RS的服务器应用程序。我正在为它添加一个端点,它将从S3存储桶中检索一个对象(也就是一个文件),将其本地保存在临时文件夹中,提供此文件,然后将其从临时文件夹中删除。所以我添加的方法之一看起来像这样:
@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()
则可行。然而,这并不理想,因为服务器并不意味着真正退出,除了重新启动很少发生。如何在输出到我的删除语句之前让它呈现输出?或者有更好的方法来解决这个问题吗?
更新:根据要求在下面添加我的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) { }
}
}
}