How to delete file after REST response [duplicate]

2019-01-18 10:21发布

This question already has an answer here:

What is the best way to handle deleting a file after it has been returned as the response to a REST request?

I have an endpoint that creates a file on request and returns it in the response. Once the response has been dispatched the file is no longer needed and can/should be removed.

@Path("file")
@GET
@Produces({MediaType.APPLICATION_OCTET_STREAM})
@Override
public Response getFile() {

        // Create the file
        ...

        // Get the file as a steam for the entity
        File file = new File("the_new_file");

        ResponseBuilder response = Response.ok((Object) file);
        response.header("Content-Disposition", "attachment; filename=\"the_new_file\"");
        return response.build();

        // Obviously I can't do this but at this point I need to delete the file!

}

I guess I could create a tmp file but I would have thought there was a more elegant mechanism to achieve this. The file could be quite large so I cannot load it into memory.

6条回答
欢心
2楼-- · 2019-01-18 10:39

save the response in a tmp variable with replacing your return statement like this:

Response res = response.build();
//DELETE your files here.
//maybe this is not the best way, at least it is a way.
return res;
查看更多
beautiful°
3楼-- · 2019-01-18 10:51

Without knowing the context of your application, you can delete the file when the VM exits:

file.deleteOnExit();    

See: https://docs.oracle.com/javase/7/docs/api/java/io/File.html#deleteOnExit%28%29

查看更多
霸刀☆藐视天下
4楼-- · 2019-01-18 10:52

I did something like this recently in rest service development using jersey

@GET
@Produces("application/zip")
@Path("/export")
public Response exportRuleSet(@QueryParam("ids") final List<String> ids) {

    try {
        final File exportFile = serviceClass.method(ruleSetIds);

        final InputStream responseStream = new FileInputStream(exportFile);


        StreamingOutput output = new StreamingOutput() {
            @Override
            public void write(OutputStream out) throws IOException, WebApplicationException {  
                int length;
                byte[] buffer = new byte[1024];
                while((length = responseStream.read(buffer)) != -1) {
                    out.write(buffer, 0, length);
                }
                out.flush();
                responseStream.close();
               boolean isDeleted = exportFile.delete();
                log.info(exportFile.getCanonicalPath()+":File is deleted:"+ isDeleted);                 
            }   
        };
        return Response.ok(output).header("Content-Disposition", "attachment; filename=rulset-" + exportFile.getName()).build();
    }
查看更多
贪生不怕死
5楼-- · 2019-01-18 10:54

There is a more elegant solution, don't write a file, just write directly to the output stream contained in the instance of Response.

查看更多
6楼-- · 2019-01-18 10:58

send file name on response:

return response.header("filetodelete", FILE_OUT_PUT).build();

after that you can send delete restful method

@POST
@Path("delete/{file}")
@Produces(MediaType.TEXT_PLAIN)
public void delete(@PathParam("file") String file) {

    File delete = new File(file);

    delete.delete();

}
查看更多
我欲成王,谁敢阻挡
7楼-- · 2019-01-18 11:00

Use a StreamingOutput as entity:

final Path path;
...
return Response.ok().entity(new StreamingOutput() {
    @Override
    public void write(final OutputStream output) throws IOException, WebApplicationException {
        try {
            Files.copy(path, output);
        } finally {
            Files.delete(path);
        }
    }
}
查看更多
登录 后发表回答