Spring @RestController-请求得到处理后

时间:2018-10-04 12:22:27

标签: java spring spring-restcontroller

背景

这是@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打开的,因此无法通过上述方法完成。

答案摘要 谢谢大家的帮助。

已接受的答案需要最少的更改并且运行良好。

4 个答案:

答案 0 :(得分:1)

除了在RESTfull服务中对GET请求执行破坏性操作是不好的做法之外,默认的Java库无法做到这一点。更为广泛接受的实现是使用GET来流式传输文件,然后执行DELETE调用以删除文件。

但是您可以通过实现自己的InputStream来做到这一点,请参见deleting files on closing a InputStream上Stackoverflow中的早期版本。

答案 1 :(得分:0)

使用您自己的实现扩展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();
    }
}

答案 2 :(得分:0)

假设您正在同一控制器中创建文件。 您可以使用:

 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返回时将关闭,因此文件将被删除。

答案 3 :(得分:0)

根据@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);
}