1. Обзор
Библиотека загрузки файлов Apache Commons помогает нам загружать большие файлы по протоколу HTTP с использованием типа multipart/form-data content.
В этом кратком руководстве мы рассмотрим, как интегрировать его с Spring.
2. Зависимости Maven
Чтобы использовать библиотеку, нам понадобится commons-fileupload артефакт:
commons-fileupload commons-fileupload 1.4
Последнюю версию можно найти на 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 .