Как удалить файл после отправки его в веб-приложение?

У меня есть веб-приложение. Я использую java и spring. Приложение может создать файл и отправить его в браузер, это работает нормально. То, как я это делаю:

Я создаю файл в классе служб, и метод возвращает адрес контроллеру. Затем контроллер отправляет файл, и он загружается правильно. Код метода контроллера таков.

@RequestMapping("/getFile")
public @ResponseBody
FileSystemResource getFile() {

    String address = Services.createFile();
    response.setContentType("application/vnd.ms-excel");
    return new FileSystemResource(new File (address));
}

проблема в том, что файл сохраняется на сервере, и после многих просьб он будет много файлов. Я должен удалить их вручную. Вопрос: Как я могу удалить этот файл после его отправки? или есть способ отправить файл без сохранения его на сервере?

3 ответов


не используйте @ResponseBody. У Весны впрыснуть HttpServletResponse и пишите прямо на свой OutputStream.

@RequestMapping("/getFile")
public void getFile(HttpServletResponse response) {
    String address = Services.createFile();
    File file = new File(address);
    response.setContentType("application/vnd.ms-excel");
    response.setHeader("Content-disposition", "attachment; filename=" + file.getName());

    OutputStream out = response.getOutputStream();
    FileInputStream in = new FileInputStream(file);

    // copy from in to out
    IOUtils.copy(in,out);

    out.close();
    in.close();
    file.delete();
}

Я не добавил никакой обработки исключений. Оставляю это тебе.

FileSystemResource это действительно просто обертка для FileInputStream это используется весной.

или, если вы хотите быть хардкор, вы можете сделать свой собственный FileSystemResource реализация со своими getOutputStream() метод, который возвращает собственную реализацию FileOutputStream удаляет исходный файл, когда вы звоните close() на нем.


поэтому я решил принять предложение Sotirious для "хардкорного" пути. Это довольно просто, но есть одна проблема. Если пользователь этого класса открывает входной поток один раз, чтобы проверить что-то и закрывает его, он не сможет открыть его снова, так как файл удаляется при закрытии. Весна, похоже, не делает этого, но вам нужно будет проверить после каждого обновления версии.

public class DeleteAfterReadeFileSystemResource extends FileSystemResource {
    public DeleteAfterReadeFileSystemResource(File file) {
        super(file);
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return new DeleteOnCloseFileInputStream(super.getFile());
    }

    private static final class DeleteOnCloseFileInputStream extends FileInputStream {

        private File file;
        DeleteOnCloseFileInputStream(File file) throws FileNotFoundException    {
            super(file);
            this.file = file;
        }

        @Override
        public void close() throws IOException {
            super.close();
            file.delete();
        }
    }
}

небольшая адаптация к ответ.

С помощью InputStreamResource вместо FileSystemResource делает это немного короче.

public class CleanupInputStreamResource extends InputStreamResource {
    public CleanupInputStreamResource(File file) throws FileNotFoundException {
        super(new FileInputStream(file) {
            @Override
            public void close() throws IOException {
                super.close();
                Files.delete(file.toPath());
            }
        });
    }
}