Spring和Apache FileUpload

2023/05/19

1. 概述

Apache Commons FileLoad库帮助我们使用multipart/form-data内容类型通过HTTP协议上传大文件。

在本快速教程中,我们将了解如何将其与Spring集成。

2. Maven依赖

要使用该库,我们需要commons-fileupload工件:

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

最新版本可以在Maven Central上找到。

3. 一次全部转移

出于演示目的,我们将创建一个控制器处理带有文件有效负载的请求:

@PostMapping("/upload")
public String handleUpload(HttpServletRequest request) throws Exception {
    boolean isMultipart = ServletFileUpload.isMultipartContent(request);

    DiskFileItemFactory factory = new DiskFileItemFactory();
    factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
    factory.setSizeThreshold(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD);
    factory.setFileCleaningTracker(null);

    ServletFileUpload upload = new ServletFileUpload(factory);

    List items = upload.parseRequest(request);

    Iterator iter = items.iterator();
    while (iter.hasNext()) {
        FileItem item = iter.next();

        if (!item.isFormField()) {
            try (InputStream uploadedStream = item.getInputStream();
                OutputStream out = new FileOutputStream("file.mov");) {

                IOUtils.copy(uploadedStream, out);
            }
        }
    }    
    return "success!";
}

一开始,我们需要使用库中ServletFileUpload类中的isMultipartContent方法检查请求是否包含多部分内容。

默认情况下,Spring具有一个MultipartResolver,我们需要禁用它才能使用此库。否则,它将在请求到达我们的控制器之前读取请求的内容。

我们可以通过在application.properties文件中包含此配置来实现此目的:

spring.http.multipart.enabled=false

现在,我们可以设置要保存文件的目录、库决定写入磁盘的阈值以及请求结束后是否应删除文件。

该库提供了一个DiskFileItemFactory类,负责文件保存和清理的配置。setRepository方法设置目标目录,示例中显示默认值。

接下来,setSizeThreshold设置最大文件大小。

然后,我们有setFileCleaningTracker方法,当设置为null时,临时文件保持不变。默认情况下,它会在请求完成后删除它们。

现在我们可以继续实际的文件处理。

首先,我们通过包含之前创建的工厂来创建我们的ServletFileUpload;然后我们继续解析请求并生成一个FileItem列表,它们是表单字段库的主要抽象。

现在,如果我们知道它不是一个普通的表单字段,那么我们将继续提取InputStream并从IOUtils调用有用的方法(有关更多选项,你可以查看本教程)。

现在我们将文件存储在必要的文件夹中。这通常是处理这种情况的更方便的方法,因为它允许轻松访问文件,但时间/内存效率也不是最佳的。

在下一节中,我们将了解流式API。

4. 流式API

流式API易于使用,使其成为处理大文件的好方法,无需到临时位置:

ServletFileUpload upload = new ServletFileUpload();
FileItemIterator iterStream = upload.getItemIterator(request);
while (iterStream.hasNext()) {
    FileItemStream item = iterStream.next();
    String name = item.getFieldName();
    InputStream stream = item.openStream();
    if (!item.isFormField()) {
        // Process the InputStream
    } else {
        String formFieldValue = Streams.asString(stream);
    }
}

我们可以在前面的代码片段中看到我们不再包含DiskFileItemFactory。这是因为,在使用流式API时,我们不需要它。

接下来,为了处理字段,该库提供了一个FileItemIterator,在我们使用下一个方法从请求中提取它们之前,它不会读取任何内容。

最后,我们可以看到如何获取其他表单域的值。

5. 总结

在本文中,我们回顾了如何将Apache Commons FileLoad库与Spring一起使用来上传和处理大文件。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章