Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/335.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用JAX-RS提供文件,然后将其删除?_Java_File_Jax Rs_Java Io_Temporary Files - Fatal编程技术网

Java 如何使用JAX-RS提供文件,然后将其删除?

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

我有一个使用JAX-RS的服务器应用程序。我正在向它添加一个端点,它将从S3 bucket中检索一个对象(也就是一个文件),将其保存在一个临时文件夹中,提供这个文件,然后将其从临时文件夹中删除。因此,我要添加的其中一种方法如下所示:

@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()。