【问题标题】:Spring @RestController - after request being servedSpring @RestController - 服务请求后
【发布时间】:2018-10-04 12:22:26
【问题描述】:

背景

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

答案摘要 感谢大家对此的帮助。

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

【问题讨论】:

标签: java spring spring-restcontroller


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

     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】:

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 2019-01-01
        • 2017-04-02
        • 2015-11-06
        • 1970-01-01
        • 2017-12-25
        • 2023-01-13
        • 2016-06-27
        • 1970-01-01
        • 2021-09-24
        相关资源
        最近更新 更多