4.5.2.1.12. FileUploadField

Компонент FileUploadField позволяет пользователю загружать файлы на сервер. Компонент может содержать заголовок, ссылку на загруженный файл и две кнопки: для загрузки файла и для очистки. При нажатии на кнопку загрузки на экране отображается стандартное для операционной системы окно, в котором можно выбрать один файл. Чтобы дать пользователю возможность загружать сразу несколько файлов, используйте компонент FileMultiUploadField.

gui upload

XML-имя компонента: upload.

gui FileUploadField dia

Компонент реализован для блоков Web Client и Desktop Client.

  • FileUploadField автоматически используется внутри FieldGroup для атрибутов типа FileDescriptor. В этом случае компонент выглядит как на приведенном выше скриншоте и не требует никакого конфигурирования. Загруженный файл сразу же сохраняется в file storage, а соответствующий FileDescriptor - в базу данных.

  • Компонент можно использовать вне FieldGroup и подключить к источнику данных. В примере ниже предполагается, что источник данных personDs содержит сущность с атрибутом photo, который является ссылкой на FileDescriptor:

    <upload fileStoragePutMode="IMMEDIATE"
            datasource="personDs"
            property="photo"/>
  • Сохранением файла и FileDescriptor можно также управлять программно.

    • Объявляем компонент в XML-дескрипторе экрана:

      <upload id="uploadField"
              fileStoragePutMode="MANUAL"/>
    • В контроллере экрана инжектируем сам компонент, а также интерфейсы FileUploadingAPI и DataSupplier. Затем в методе init() добавляем слушатели, которые будут реагировать на события успешной загрузки или ошибки:

      @Inject
      private FileUploadField uploadField;
      @Inject
      private FileUploadingAPI fileUploadingAPI;
      @Inject
      private DataSupplier dataSupplier;
      
      @Override
      public void init(Map<String, Object> params) {
          uploadField.addFileUploadSucceedListener(event -> {
              FileDescriptor fd = uploadField.getFileDescriptor();
              try {
                  // save file to FileStorage
                  fileUploadingAPI.putFileIntoStorage(uploadField.getFileId(), fd);
              } catch (FileStorageException e) {
                  throw new RuntimeException("Error saving file to FileStorage", e);
              }
              // save file descriptor to database
              dataSupplier.commit(fd);
              showNotification("Uploaded file: " + uploadField.getFileName(), NotificationType.HUMANIZED);
          });
      
          uploadField.addFileUploadErrorListener(event ->
                  showNotification("File upload error", NotificationType.HUMANIZED));
      }

      Компонент загружает файл во временное хранилище клиентского уровня и вызывает листенер, добавленный методом addFileUploadSucceedListener(). В этом листенере у компонента запрашивается объект FileDescriptor, соответствующий загруженному файлу. Объект com.haulmont.cuba.core.entity.FileDescriptor является персистентной сущностью, которая однозначно идентифицирует загруженный файл и впоследствии используется для выгрузки файла из системы.

      Метод FileUploadingAPI.putFileIntoStorage() используется для перемещения загружаемого файла из временного хранилища клиентского уровня в FileStorage. Параметрами этого метода являются идентификатор файла во временном хранилище и объект FileDescriptor. Оба эти параметра предоставляет FileUploadField.

      После загрузки файла в FileStorage выполняется сохранение экземпляра FileDescriptor в базе данных посредством вызова DataSupplier.commit(). Возвращаемый этим методом сохраненный экземпляр может быть установлен в атрибут какой-либо сущности предметной области, связанной с данным файлом. В данном же случае FileDescriptor просто сохраняется в базе данных. Соответствующий файл будет доступен через экран AdministrationExternal Files.

      Листенер, добавленный методом addFileUploadErrorListener() вызывается в случае ошибки загрузки файла во временное хранилище клиентского уровня.

  • XML-атрибут fileStoragePutMode задает режим сохранения файла и соответствующего FileDescriptor. В режиме IMMEDIATE это делается автоматически сразу после загрузки файла во временное хранилище клиентского уровня. В режиме MANUAL необходимо сделать это в листенере FileUploadSucceedListener. Режим IMMEDIATE выбирается по умолчанию, когда FileUploadField используется внутри FieldGroup. В противном случае, по умолчанию выбирается MANUAL.

  • XML-атрибуты uploadButtonCaption, uploadButtonIcon и uploadButtonDescription позволяют задать параметры кнопки загрузки.

  • XML-атрибут showClearButton управляет видимостью кнопки очистки. По умолчанию false.

  • XML-атрибуты clearButtonCaption, clearButtonIcon и clearButtonDescription позволяют задать параметры кнопки очистки, если она видима.

  • XML-атрибут accept (и соответствующий метод setAccept()) может быть использован для установки маски расширений файлов в диалоге выбора файла. Пользователи будут иметь возможность выбрать "All files" и загрузить произвольные файлы.

    Значением атрибута должен быть список масок, разделенных запятыми. Например: *.jpg,*.png.

  • Максимальный размер загружаемого файла определяется свойством приложения cuba.maxUploadSizeMb и по умолчанию равен 20MB. При выборе пользователем файла большего размера выдается соответствующее сообщение и загрузка прерывается.

  • XML-атрибут fileSizeLimit (и соответствующий метод setFileSizeLimit()) может быть использован для установки максимально допустимого размера файла. Значением атрибута должно быть целое число для указания количества байт.

    <upload id="uploadField" fileSizeLimit="2000"/>
  • XML-атрибут permittedExtensions (и соответствующий метод setPermittedExtensions()) может быть использован для установки допустимых расширений загружаемых файлов. Если атрибут установлен, пользователи не смогут загрузить файлы с неразрешенными расширениями.

    Значением атрибута должен быть список расширений с лидирующими точками, разделенных запятыми. Например: .jpg,.jpeg,.png,.gif.

  • XML-атрибут dropZone используется для указания BoxLayout, который будет использован в качестве целевой площадки для перетаскивания файлов извне браузера. Зона перетаскивания может занимать всю площадь диалогового окна. Выбранный контейнер будет подсвечиваться, когда пользователь переносит над ним файлы, без наведения файла контейнер не отображается.

    <layout spacing="true"
            width="100%">
        <vbox id="dropZone"
              height="AUTO"
              spacing="true">
            <textField id="textField"
                       caption="Title"
                       width="100%"/>
            <textArea id="textArea"
                      caption="Description"
                      width="100%"
                      rows="5"/>
            <checkBox caption="Is reference document"
                      width="100%"/>
            <upload id="upload"
                    dropZone="dropZone"
                    showClearButton="true"
                    showFileName="true"/>
        </vbox>
        <hbox spacing="true">
            <button caption="mainMsg://actions.Apply"/>
            <button caption="mainMsg://actions.Cancel"/>
        </hbox>
    </layout>
    gui dropZone

    Чтобы сделать область dropZone статической и отображать её постоянно, необходимо назначить её контейнеру готовый стиль dropzone-container. В этом случае контейнер необходимо оставить пустым, поместив в него только текстовый компонент label:

    <layout spacing="true"
            width="100%">
        <textField id="textField"
                   caption="Title"
                   width="100%"/>
        <checkBox caption="Is reference document"
                  width="100%"/>
        <upload id="upload"
                dropZone="dropZone"
                showClearButton="true"
                showFileName="true"/>
        <vbox id="dropZone"
              height="150px"
              spacing="true"
              stylename="dropzone-container">
            <label stylename="dropzone-description"
                   value="Drop file here"
                   align="MIDDLE_CENTER"/>
        </vbox>
        <hbox spacing="true">
            <button caption="mainMsg://actions.Apply"/>
            <button caption="mainMsg://actions.Cancel"/>
        </hbox>
    </layout>
    gui dropZone static

В разделе Загрузка и вывод изображений приведен более сложный пример работы с загруженными файлами.