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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17933508/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 19:39:44  来源:igfitidea点击:

How to delete a file after sending it in a web app?

javaspringfileweb-applicationsfile-upload

提问by ia.solano

I have a web application. I am using java and spring. The application can create a file and send it to the browser, this is working fine. The way I do it is:

我有一个网络应用程序。我正在使用 java 和 spring。该应用程序可以创建一个文件并将其发送到浏览器,这工作正常。我的做法是:

I create the file in a Services class, and the method returns the address to the controller. The controller then sends the file, and it is downloaded correctly. The code for the controller method is this.

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

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

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

The problem is that the file is saved in the server, and after many requests it will have a lot of files. I have to delete them manually. The question is: How can I delete this file after sending it? or Is there a way to send the file without saving it in the server?

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

回答by Sotirios Delimanolis

Don't use @ResponseBody. Have Spring inject the HttpServletResponseand write directly to its OutputStream.

不要使用@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();
}

I haven't added any exception handling. I leave that to you.

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

FileSystemResourceis really just is a wrapper for FileInputStreamthat's used by Spring.

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

Or, if you want to be hardcore, you could make your own FileSystemResourceimplementation with its own getOutputStream()method that returns your own implementation of FileOutputStreamthat deletes the underlying file when you call close()on it.

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

回答by Mag

So I decided to take Sotirious's suggestion for a "hardcore" way. It is pretty simple, but has one problem. If user of that class opens input stream once to check something and closes it, it will not be able to open it again since file is deleted on close. Spring does not seem to do that, but you will need to check after every version upgrade.

所以我决定采纳 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();
        }
    }
}

回答by kuhnroyal

A minor adaption to this answer.

这个答案的小改动。

Using a InputStreamResourceinstead of FileSystemResourcemakes this a little shorter.

使用 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());
            }
        });
    }
}