1. Overview
1.概述
The Apache Commons File Upload Library helps us upload large files over the HTTP protocol using the multipart/form-data content type.
Apache Commons File Upload Library帮助我们使用multipart/form-data内容类型通过HTTP协议上传大型文件。
In this quick tutorial, we’re going to take a look at how to integrate it with Spring.
在这个快速教程中,我们将看看如何将其与Spring集成。
2. Maven Dependencies
2.Maven的依赖性
To use the library, we’ll need the commons-fileupload artifact:
要使用这个库,我们需要commons-fileupload工件。
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
The latest version can be found on Maven Central.
最新版本可以在Maven Central上找到。
3. Transfering All at Once
3.一次性转移
For demonstration purposes, we’re going to create a Controller processing requests with a file payload:
为了演示,我们将创建一个Controller处理带有文件有效载荷的请求。
@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!";
}
In the beginning, we need to check if the request contains a multipart content using the isMultipartContent method found in the ServletFileUpload class from the library.
一开始,我们需要使用库中的ServletFileUpload类中的isMultipartContent方法检查请求是否包含多部分内容。
By default, Spring features a MultipartResolver that we’ll need to disable to use this library. Otherwise, it’ll read the content of the request before it reaches our Controller.
默认情况下,Spring具有一个MultipartResolver,我们需要禁用这个库。否则,它将在请求到达我们的Controller之前读取其内容。
We can achieve this by including this configuration in our application.properties file:
我们可以通过在application.properties文件中加入这一配置来实现这一目标。
spring.http.multipart.enabled=false
Now, we can set the directory where our files are going to be saved, the threshold in which the library decides to write to disk and if files should be deleted after the request ends.
现在,我们可以设置我们的文件将被保存的目录,库决定写入磁盘的阈值,以及在请求结束后是否应删除文件。
The library provides a DiskFileItemFactory class that takes the responsibility of the configuration for the file saving and cleaning. The setRepository method sets the target directory, with the default being shown in the example.
该库提供了一个DiskFileItemFactory类,负责文件保存和清理的配置。setRepository方法设置了目标目录,默认的是例子中所示。
Next, the setSizeThreshold sets a maximum file size.
接下来,setSizeThreshold设置一个最大的文件大小。
Then, we have the setFileCleaningTracker method that, when set to null, leaves the temporary files untouched. By default, it deletes them after the request has finished.
然后,我们有一个setFileCleaningTracker方法,当设置为null时,它将不触动临时文件。默认情况下,它将在请求结束后删除它们。
Now we can continue to the actual file handling.
现在我们可以继续进行实际的文件处理。
First, we create our ServletFileUpload by including our previously created factory; then we proceed to parse the request and generate a list of FileItem which are the main abstraction of the library for the form fields.
首先,我们创建我们的ServletFileUpload,包括我们之前创建的工厂;然后我们继续解析请求并生成FileItem的列表,这是表单字段的主要抽象库。
Now if we know it isn’t a normal form field, then we proceed to extract the InputStream and to call the useful copy method from IOUtils (for more options you can have a look at this tutorial).
现在,如果我们知道它不是一个正常的表单字段,那么我们继续提取InputStream,并从IOUtils中调用有用的复制方法(更多选项你可以看看这个教程)。
Now we have our file stored in the necessary folder. This is usually a more convenient way to handle this situation as it allows easy access to the files, but also time/memory efficiency isn’t optimal.
现在我们的文件已经存储在必要的文件夹中。这通常是处理这种情况的一个更方便的方法,因为它允许轻松访问文件,但同时时间/内存效率也不是最佳。
In the next section, we’re going to take a look at the streaming API.
在下一节中,我们要看一下流媒体API。
4. Streaming API
4.流媒体API
The streaming API is easy to use, making it a great way to process large files simply by not copying to a temporary location:
流媒体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);
}
}
We can see in the previous code snippet that we no longer include a DiskFileItemFactory. This is because, when using the streaming API, we don’t need it.
我们可以在之前的代码片段中看到,我们不再包含一个DiskFileItemFactory。这是因为,当使用流媒体API时,我们不需要它。
Next, to process fields, the library provides a FileItemIterator, which doesn’t read anything until we extract them from the request with the next method.
接下来,为了处理字段,该库提供了一个FileItemIterator,在我们用next方法从请求中提取它们之前,它不会读取任何东西。
Finally, we can see how to obtain the values of the other form fields.
最后,我们可以看看如何获得其他表单字段的值。
5. Conclusion
5.结论
In this article, we’ve reviewed how we can use the Apache Commons File Upload Library with Spring to upload and process large files.
在这篇文章中,我们回顾了如何使用Apache Commons文件上传库和Spring来上传和处理大文件。
As always the full source code can be found over at GitHub.
一如既往,完整的源代码可以在GitHub上找到,。