如何在Web应用程序中发送文件后删除?

ia.*_*ano 11 java spring file-upload web-applications file

我有一个Web应用程序.我正在使用java和spring.应用程序可以创建一个文件并将其发送到浏览器,这很好.我这样做的方式是:

我在Services类中创建该文件,该方法将地址返回给控制器.然后控制器发送文件,并正确下载.控制器方法的代码是这样的.

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

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

问题是文件保存在服务器中,经过多次请求后会有很多文件.我必须手动删除它们.问题是:如何在发送后删除此文件?或者有没有办法发送文件而不将其保存在服务器中?

Sot*_*lis 17

不要用@ResponseBody.有Spring注入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();
}
Run Code Online (Sandbox Code Playgroud)

我没有添加任何异常处理.我把它留给你.

FileSystemResource实际上它只是FileInputStreamSpring使用的包装器.

或者,如果你想成为硬核,你可以FileSystemResource使用自己的getOutputStream()方法创建自己的实现,该方法返回你自己的实现,FileOutputStream当你调用close()它时删除底层文件.

  • 当文件非常大时,此解决方案会出现问题。IOUtils.copy(in,out) 抛出 OutOfMemoryException。 (2认同)

Mag*_*Mag 10

所以我决定采纳 Sotirious 的“硬核”方式建议。这很简单,但有一个问题。如果该类的用户打开输入流一次以检查某些内容并关闭它,它将无法再次打开它,因为文件在关闭时被删除。Spring 似乎没有这样做,但是您需要在每次版本升级后进行检查。

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


kuh*_*yal 8

这个答案的小改动。

使用 aInputStreamResource而不是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());
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

您可以使用匿名类编写 Mag 的解决方案,如下所示:

new FileSystemResource(file) {
    @Override
    public InputStream getInputStream() throws IOException {
        return new FileInputStream(file) {
            @Override
            public void close() throws IOException {
                super.close();
                Files.delete(file.toPath());
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)