Send temp file with jax-rs

2019-05-11 15:31发布

问题:

I am trying to send a temporary file with jax-rs and delete the temporary file once the download is done. For that purpose I subclassed InputSream in order to be notified once the stream is closed. This is what I have so far:

@GET
@Path("download/{fileName}")
public Response downloadFile(@PathParam("fileName") String fileName) {
    InputStream inputStream = new InputStreamWithFileDeletion(new getFile(filename));

    Response.ResponseBuilder response = Response.ok((Object) file);
    response.header("Content-Disposition",
            "attachment; filename="+"fileName"+".xls");
    return response.build();
}

InputStreamWithFileDeletion:

public class InputStreamWithFileDeletion extends FileInputStream {
    File f;

    public InputStreamWithFileDeletion(File file) throws FileNotFoundException {
        super(file);
        f = file;
    }

    @Override
    public void close() throws IOException {
        super.close();
        f.delete();
    }
}

Unfortunately, once the download is done, close() is not called. Am I missing something?

回答1:

Change

Response.ResponseBuilder response = Response.ok((Object) file);

to

Response.ResponseBuilder response = Response.ok(inputStream);


回答2:

Based on Sven Junga's answer, I came up with this solution:

Path p = Paths.get(tempFile);
InputStream is = Files.newInputStream(p);
Files.delete(p);
return Response.ok(is).header("Content-Disposition", "attachment; filename=f.txt").build();

The file will be deleted as soon as the input stream is consumed.



回答3:

Change this line

InputStream inputStream = new InputSreamWithFileDelition(new getFile(filename));

to

InputSreamWithFileDelitioninputStream = new InputSreamWithFileDelition(new getFile(filename));

to make sure to call the good close method.

Then implement AutoCloseAble in your InputStreamWithFileDelition class which will call by default your overriden close method.