Отображение P:fileupload с изображения в P:графического изображения предварительного просмотра без сохранения
Я использую PrimeFaces 5.3 <p:fileUpload>
для загрузки изображения PNG, и я хотел бы показать предварительный просмотр его в <p:graphicImage>
перед сохранением в базе данных.
Вот MCVE:
<h:form enctype="multipart/form-data">
<p:fileUpload value="#{bean.uploadedFile}" mode="simple" />
<p:graphicImage value="#{bean.image}" />
<p:commandButton action="#{bean.preview}" ajax="false" value="Preview" />
</h:form>
private UploadedFile uploadedFile;
public UploadedFile getUploadedFile() {
return uploadedFile;
}
public void setUploadedFile(UploadedFile uploadedFile) {
this.uploadedFile = uploadedFile;
}
public void preview() {
// NOOP for now.
}
public StreamedContent getImage() {
if (uploadedFile == null) {
return new DefaultStreamedContent();
} else {
return new DefaultStreamedContent(new ByteArrayInputStream(uploadedFile.getContents()), "image/png");
}
}
Нет ошибок, возникающих на бэк-Бобе, и изображение не будет загружаться и отображаться на переднем конце. Клиент упоминает, что изображение вернуло ошибку 404 not found.
1 ответ:
Ваша проблема двоякая. Это не удалось, потому что загруженное содержимое файла является областью запроса и потому что изображение запрашивается в другом HTTP-запросе. Чтобы лучше понять внутреннюю работу, внимательно прочитайте ответы на следующие тесно связанные вопросы и ответы:
- отображение динамического изображения из базы данных с помощью p: graphicImage и StreamedContent
- Как правильно выбрать область применения бобов?
Чтобы решить первую задачу, вам необходимо прочитать загруженное содержимое файла немедленно в методе действия, связанном с формой submit. В вашем конкретном случае это будет выглядеть следующим образом:
private UploadedFile uploadedFile; private byte[] fileContents; public void preview() { fileContents = uploadedFile.getContents(); } // ...
, Чтобы решить вторую проблему, ваш лучший выбор должен использовать данные схемы URI. Это позволяет визуализировать образ непосредственно в том же самом ответе, и поэтому вы можете безопасно использовать боб
@ViewScoped
, не сталкиваясь с проблемами "контекст не активен" или сохраняяbyte[]
в сеансе или диске, чтобы позволить обслуживать образ в другом контексте. запрос. поддержка браузеров по схеме data URI в настоящее время довольно хороша. Заменить весь текст<p:graphicImage>
следующим текстом:<ui:fragment rendered="#{not empty bean.uploadedFile}"> <img src="data:image/png;base64,#{bean.imageContentsAsBase64}" /> </ui:fragment>
public String getImageContentsAsBase64() { return Base64.getEncoder().encodeToString(imageContents); }
Примечание: Я предполагаю, что Java 8 доступна вам как
java.util.Base64
был представлен только в этой версии. Если вы используете старую версию Java, используйтеDatatypeConverter.printBase64Binary(imageContents)
вместо этого.Если вы используете служебную библиотеку JSF OmniFaces , вы также можете просто использовать ее
<o:graphicImage>
компонент вместо которого включен в отличие от<p:graphicImage>
, способного напрямую ссылаться на свойствоbyte[]
иInputStream
bean и отображать URI данных.<o:graphicImage value="#{bean.imageContents}" dataURI="true" rendered="#{not empty bean.imageContents}">