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.

Резюме Ответа Спасибо всем за помощь в этом.

Принятый ответ требует наименьших изменений и работает хорошо.

3 ответа

Решение

Простираться 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();
    }
}

Несмотря на тот факт, что в службе RESTfull выполнять деструктивные операции над запросами GET недопустимо, это не может быть сделано библиотеками Java по умолчанию. Более широко принятой реализацией будет GET, который транслирует файл с последующим вызовом DELETE для его удаления.

Но вы можете сделать это, реализовав свой собственный InputStream, см. Более раннюю тему в Stackru об удалении файлов при закрытии InputStream.

Предполагая, что вы создаете файл в том же контроллере. Ты можешь использовать:

 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 закроется по возвращении, файл будет удален.

Основываясь на ответе @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);
}
Другие вопросы по тегам