Spring и Apache FileUpload

Spring и Apache FileUpload

1. обзор

Apache Commons File Upload Library помогает нам загружать большие файлы по протоколу HTTP с использованием типа содержимогоmultipart/form-data.

В этом кратком руководстве мы рассмотрим, как интегрировать его со Spring.

2. Maven Зависимости

Для использования библиотеки нам понадобится артефактcommons-fileupload:


    commons-fileupload
    commons-fileupload
    1.3.3

Последнюю версию можно найти наMaven Central.

3. Перенос всех сразу

В демонстрационных целях мы собираемся создать запрос обработки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!";
}

Вначалеwe need to check if the request contains a multipart content использует методisMultipartContent, найденный в классеServletFileUpload из библиотеки.

По умолчаниюSpring features aMultipartResolverthat we’ll need to disable to use this library. В противном случае он прочитает содержимое запроса до того, как достигнет нашегоController.

Мы можем добиться этого, включив эту конфигурацию в наш файлapplication.properties:

spring.http.multipart.enabled=false

Теперь мы можем установить каталог, в который будут сохраняться наши файлы, порог, в котором библиотека решает записать данные на диск, и следует ли удалять файлы после завершения запроса.

Библиотека предоставляет классDiskFileItemFactory, в котором метод_ takes the responsibility of the configuration for the file saving and cleaning. The _setRepository устанавливает целевой каталог, причем значение по умолчанию показано в примере.

ЗатемsetSizeThreshold устанавливает максимальный размер файла.

Затем у нас есть методsetFileCleaningTracker, который при значении null оставляет временные файлы нетронутыми. By default, it deletes them after the request has finished.

Теперь мы можем перейти к фактической обработке файлов.

Сначала мы создаемServletFileUpload, включая ранее созданную фабрику; затем мы переходим к синтаксическому анализу запроса и генерируем списокFileItem, который является основной абстракцией библиотеки для полей формы.

Теперь, если мы знаем, что это не поле нормальной формы, мы приступаем к извлечениюInputStream и вызову полезного метода копирования изIOUtils (дополнительные параметры вы можете посмотреть наthis) s учебник).

Теперь наш файл хранится в нужной папке. Обычно это более удобный способ справиться с этой ситуацией, поскольку он обеспечивает легкий доступ к файлам, но эффективность использования времени / памяти не является оптимальной.

В следующем разделе мы рассмотрим 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. Это потому, чтоwhen using the streaming API, we don’t need it.

Затем для обработки полей библиотека предоставляетFileItemIterator, который ничего не читает, пока мы не извлечем их из запроса с помощью методаnext.

Наконец, мы можем видеть, как получить значения других полей формы.

5. Заключение

В этой статье мы рассмотрели, как мы можем использовать библиотеку загрузки файлов Apache Commons со Spring для загрузки и обработки больших файлов.

Как всегда, полный исходный код можно найтиover at GitHub.