1. Обзор
Библиотека загрузки файлов Apache Commons помогает нам загружать большие файлы по протоколу HTTP, используя тип содержимого multipart/form-data .
В этом кратком руководстве мы рассмотрим, как интегрировать его с 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!";
}
В начале нам нужно проверить, содержит ли запрос составной контент , используя метод isMultipartContent
, найденный в классе ServletFileUpload
из библиотеки.
По умолчанию в 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
, который ничего не читает, пока мы не извлечем их из запроса с помощью метода next .
Наконец, мы можем увидеть, как получить значения других полей формы.
5. Вывод
В этой статье мы рассмотрели, как мы можем использовать библиотеку загрузки файлов Apache Commons с Spring для загрузки и обработки больших файлов.
Как всегда, полный исходный код можно найти на GitHub .