Запись файла на диск с использованием 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, а не на класс bean. В принципе, эта аннотация должна быть помещена в класс FacesServlet, который уже выполняется с JSF 2.2.

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

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

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

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

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

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

См. также


Несвязанный к конкретной проблеме, с помощью сеанса bean для этой цели не является идеальным. Скорее используйте просмотр или запрос с областью действия. См. Также Как правильно выбрать область bean? И использование prependId="false" не рекомендуется для других целей, кроме форм входа, привязанных к структуре входа, которая не поддержка JSF-preend ID в именах параметров запроса. См. Также UIForm с prependId = "false" breaks < f: ajax render > .