Записать файл на диск, используя JSF 2.2 inputFile

Я пытаюсь загрузить файл изображения с помощью тега h:inputFile и записать его на диск.

Мой код JSF:

<h:form id="fileUploadForm" enctype='multipart/form-data' prependId="false">
   <h:inputFile value="#{solicitacaoManagedBean.imagemCarregada}" />
   <br />
   <h:commandButton styleClass="btn btn-primary " value="Enviar" action="#{solicitacaoManagedBean.enviarImagem}" />
</h:form>

Мой ManagedBean:

@Named(value = "solicitacaoManagedBean")
@SessionScoped
@MultipartConfig(location = "/home/rogerio/tmp/")
public class SolicitacaoManagedBean implements Serializable {

   private Part imagemCarregada;

(...)

   public void enviarImagem() throws IOException {
      try {
         imagemCarregada.write("teste.jpg");
      } catch (IOException ioe) {
         System.out.println("Erro ao escrever: " + ioe.getLocalizedMessage());
      }
   }
}

Предположительно, метод write загружает элемент на диск, и IOException также не выбрасывается / перехватывается.

1 ответ

Решение

@javax.servlet.annotation.MultipartConfig аннотация должна быть размещена на классе, реализующем HttpServlet не на бэк-классе. По сути, эта аннотация должна быть размещена на FacesServlet класс, который уже сделан с JSF 2.2.

Другими словами, @MultipartConfig аннотация к классу компонента поддержки игнорируется и не имеет никакого эффекта, и файл фактически не сохраняется в location Вы указали в аннотации. Вместо этого он был сохранен в пути относительно так называемого текущего рабочего каталога, который на данный момент является "текущей открытой папкой" java.exe был выполнен. В случае веб-приложений Java это обычно двоичная папка сервера или около того. Вы можете отследить это, как показано ниже:

System.out.println(new File(".").getAbsolutePath());

Вы увидите ваш загруженный файл там.

Более того, даже если @MultipartConfig аннотация сработала, location Атрибут на самом деле не представляет место сохранения файла постоянной загрузки. Вместо этого он представляет временное место на диске для случая, когда размер загружаемого файла превышает доступное / настроенное пространство памяти. Вы никогда не должны хранить загруженные файлы постоянно в месте, указанном @MultipartConfig(location), Вы всегда должны получать содержимое файла через Part#getInputStream() и запишите его в нужное постоянное место, предоставленное новым File или же Path представляющий абсолютный путь.

Избавиться от всего этого @MultipartConfig аннотаций. Он не делает ничего полезного в классе бина. Просто получите содержимое файла Part#getInputStream() и скопируйте его в нужный абсолютный путь:

try (InputStream input = imagemCarregada.getInputStream()) {
    Files.copy(input, new File("/home/rogerio/tmp/teste.jpg").toPath());
}

Смотрите также


Независимо от конкретной проблемы, использование для этой цели bean-объекта сессионной области не является идеальным. Скорее используйте представление или запрос, ограниченный. Смотрите также Как правильно выбрать сферу применения бобов? И, используя prependId="false" не рекомендуется для других целей, кроме форм входа в систему, связанных с каркасом входа в систему, который не поддерживает идентификатор с добавлением JSF в именах параметров запроса. Смотрите также UIForm с prependId="false" breaks ;.

Другие вопросы по тегам