Spring @RestController - 服务请求后
Spring @RestController - after request being served
背景
这是@RestController 中定义的方法,它从磁盘读取文件然后流回。
@RequestMapping(value = "/bill", method = RequestMethod.GET)
public ResponseEntity<Object> getbill(){
...
InputStream in = new FileInputStream(file);
InputStreamResource inputStreamResource = new InputStreamResource(in);
httpHeaders.setContentLength(file.Length());
return new ResponseEntity(inputStreamResource, httpHeaders, HttpStatus.OK);
}
问题
我想在收到请求后删除该文件,但找不到合适的位置。
我认为应该是在 inputStream 关闭 (https://github.com/spring-projects/spring-framework/blob/v4.3.9.RELEASE/spring-web/src/main/java/org/springframework/http/converter/ResourceHttpMessageConverter.java#L117) 之后。上面的方法无法完成,因为文件是由 Inputstream 打开的。
答案摘要
谢谢大家的帮助。
已接受的答案需要最少的更改并且运行良好。
除了在 RESTfull 服务中对 GET 请求执行破坏性操作是不好的做法之外,默认的 Java 库无法做到这一点。更广泛接受的实现是 GET,它流式传输文件,然后是删除文件的 DELETE 调用。
但是您可以通过实现自己的 InputStream 来实现,请参阅 deleting files on closing a InputStream 上 Whosebug 中的早期线程。
用您自己的实现扩展 FileInputStream
,然后覆盖 close
。当输入流关闭时,您的文件也会被删除。
public class MyFileInputStream extends FileInputStream {
private final File myFile;
public MyFileInputStream(File file) throws FileNotFoundException {
super(file);
myFile = file;
}
@Override
public void close() throws IOException {
super.close();
myFile.delete();
}
}
假设您在同一个控制器中创建文件。
您可以使用:
try (BufferedWriter out = Files
.newBufferedWriter(newFilePath, Charset.defaultCharset(),
StandardOpenOption.DELETE_ON_CLOSE)) {
InputStream in = new FileInputStream(newFilePath.toFile());
InputStreamResource inputStreamResource = new InputStreamResource(in);
httpHeaders.setContentLength(file.Length());
return new ResponseEntity(inputStreamResource, httpHeaders, HttpStatus.OK);
} catch (Exception e) {
}
由于 BufferedWriter 将在 return 关闭,文件将被删除。
根据@phlogratos的回答,你可以这样试试
@GetMapping("/download")
public ResponseEntity<InputStreamResource> download() throws Exception {
... codes ...
InputStreamResource isr = new InputStreamResource(new FileInputStream(file) {
@Override
public void close() throws IOException {
super.close();
boolean isDeleted = file.delete();
logger.info("export:'{}':" + (isDeleted ? "deleted" : "preserved"), filename);
}
});
return new ResponseEntity<>(isr, respHeaders, HttpStatus.OK);
}
背景
这是@RestController 中定义的方法,它从磁盘读取文件然后流回。
@RequestMapping(value = "/bill", method = RequestMethod.GET)
public ResponseEntity<Object> getbill(){
...
InputStream in = new FileInputStream(file);
InputStreamResource inputStreamResource = new InputStreamResource(in);
httpHeaders.setContentLength(file.Length());
return new ResponseEntity(inputStreamResource, httpHeaders, HttpStatus.OK);
}
问题
我想在收到请求后删除该文件,但找不到合适的位置。
我认为应该是在 inputStream 关闭 (https://github.com/spring-projects/spring-framework/blob/v4.3.9.RELEASE/spring-web/src/main/java/org/springframework/http/converter/ResourceHttpMessageConverter.java#L117) 之后。上面的方法无法完成,因为文件是由 Inputstream 打开的。
答案摘要 谢谢大家的帮助。
已接受的答案需要最少的更改并且运行良好。
除了在 RESTfull 服务中对 GET 请求执行破坏性操作是不好的做法之外,默认的 Java 库无法做到这一点。更广泛接受的实现是 GET,它流式传输文件,然后是删除文件的 DELETE 调用。
但是您可以通过实现自己的 InputStream 来实现,请参阅 deleting files on closing a InputStream 上 Whosebug 中的早期线程。
用您自己的实现扩展 FileInputStream
,然后覆盖 close
。当输入流关闭时,您的文件也会被删除。
public class MyFileInputStream extends FileInputStream {
private final File myFile;
public MyFileInputStream(File file) throws FileNotFoundException {
super(file);
myFile = file;
}
@Override
public void close() throws IOException {
super.close();
myFile.delete();
}
}
假设您在同一个控制器中创建文件。 您可以使用:
try (BufferedWriter out = Files
.newBufferedWriter(newFilePath, Charset.defaultCharset(),
StandardOpenOption.DELETE_ON_CLOSE)) {
InputStream in = new FileInputStream(newFilePath.toFile());
InputStreamResource inputStreamResource = new InputStreamResource(in);
httpHeaders.setContentLength(file.Length());
return new ResponseEntity(inputStreamResource, httpHeaders, HttpStatus.OK);
} catch (Exception e) {
}
由于 BufferedWriter 将在 return 关闭,文件将被删除。
根据@phlogratos的回答,你可以这样试试
@GetMapping("/download")
public ResponseEntity<InputStreamResource> download() throws Exception {
... codes ...
InputStreamResource isr = new InputStreamResource(new FileInputStream(file) {
@Override
public void close() throws IOException {
super.close();
boolean isDeleted = file.delete();
logger.info("export:'{}':" + (isDeleted ? "deleted" : "preserved"), filename);
}
});
return new ResponseEntity<>(isr, respHeaders, HttpStatus.OK);
}