Отображение загруженного изображения в JSF
у меня есть боб с областью видимости, где я создаю человека. У человека может быть фотография. Эта картинка загружается той же странице Человек создан. Изображение не хранится в базе данных или на диске (поскольку человек еще не создан). Боб должен быть просмотрен, так как человек может быть создан в другом месте, и это использует тот же Боб. Если компонент имеет область сеанса и пользователь загружает изображение, но не сохраняет человека, изображение будет отображаться при следующей попытке создать человек.
я решил это с помощью двух бобов; один вид области Боба для создания человека и сеанса области Боба, чтобы загрузить изображение и получить изображение в виде потока. Это, однако, вызывает проблему, указанную выше.
как я могу решить эту проблему лучше?
загрузка в зернах:
@ManagedBean(name = "uploadBean")
@SessionScoped
public class UploadBean
{
private UploadedFile uploadedFile;
public UploadedFile getUploadedFile()
{
return uploadedFile;
}
public StreamedContent getUploadedFileAsStream()
{
if (uploadedFile != null)
{
return new DefaultStreamedContent(new ByteArrayInputStream(uploadedFile.getContents()));
}
return null;
}
public void uploadFile(FileUploadEvent event)
{
uploadedFile = event.getFile();
}
}
Боб создания человека:
@ManagedBean(name = "personBean")
@ViewScoped
public class PersonBean
{
private Person newPerson = new Person();
public Person getNewPerson()
{
return newPerson;
}
private UploadedFile getUploadedPicture()
{
FacesContext context = FacesContext.getCurrentInstance();
ELContext elContext = context.getELContext();
UploadBean uploadBean = (UploadBean) elContext.getELResolver().getValue(elContext, null, "uploadBean");
return uploadBean.getUploadedFile();
}
public void createPerson()
{
UploadedFile uploadedPicture = getUploadedPicture();
// Create person with picture;
}
}
соответствующая часть страницы JSF:
<h:form enctype="multipart/form-data">
<p:outputPanel layout="block" id="personPicture">
<p:graphicImage height="150"
value="#{uploadBean.uploadedFileAsStream}"
rendered="#{uploadBean.uploadedFileAsStream != null}" />
</p:outputPanel>
<p:fileUpload auto="true" allowTypes="/(.|/)(gif|jpe?g|png)$/"
fileUploadListener="#{uploadBean.uploadedFile}"
update="personPicture" />
<p:commandButton value="Save" actionListener="#{personBean.createPerson()}"/>
</h:form>
2 ответов
Я пошел на другой подход. Сначала я пошел для отображения загруженного изображения, однако, если Person
еще не создан, казалось бы, лучшая идея сохранить все это на стороне клиента. Я нашел этот вопрос и созданы на основе выбранного ответа:
в голову включаю html5shiv если браузер IE и версия меньше 9 для совместимости:
<h:outputText value="<!--[if lt IE 9]>" escape="false" />
<h:outputScript library="js" name="html5shiv.js" />
<h:outputText value="<![endif]-->" escape="false" />
для отображения/загрузки изображения у меня эти элементы:
<p:fileUpload binding="#{upload}" mode="simple"
allowTypes="/(\.|\/)(gif|jpe?g|png)$/"
value="#{personBean.uploadedPicture}"/>
<p:graphicImage value="#" height="150" binding="#{image}" />
и некоторые JavaScript / jQuery magic:
function readPicture(input, output)
{
if (input.files && input.files[0])
{
var reader = new FileReader();
reader.onload = function(e)
{
output.attr('src', e.target.result);
};
reader.readAsDataURL(input.files[0]);
}
}
$("[id='#{upload.clientId}']").change(
function()
{
readPicture(this, $("[id='#{image.clientId}']"));
});
на uploadedPicture
свойство теперь простое свойство:
@ManagedBean(name = "personBean")
@ViewScoped
public class PersonBean
{
private UploadedFile uploadedPicture;
public UploadedFile getUploadedPicture()
{
return uploadedPicture;
}
public void setUploadedPicture(UploadedFile uploadedPicture)
{
this.uploadedPicture = uploadedPicture;
}
}
добавить.в XHTML
<h:form id="add-form" enctype="multipart/form-data">
<p:growl id="messages" showDetail="true"/>
<h:panelGrid columns="2">
<p:outputLabel for="choose" value="Choose Image :" />
<p:fileUpload id="choose" validator="#{productController.validateFile}" multiple="false" allowTypes="/(\.|\/)(gif|jpe?g|png)$/" value="#{productController.file}" required="true" mode="simple"/>
<p:commandButton value="Submit" ajax="false" update="messages" id="save-btn" actionListener="#{productController.saveProduct}"/>
</h:panelGrid>
</h:form>
вот управляемый бобовый код:
@ManagedBean
@RequestScoped
public class ProductController implements Serializable{
private ProductBean bean;
@ManagedProperty(value = "#{ProductService}")
private ProductService productService;
private StreamedContent content;
private UploadedFile file;
public StreamedContent getContent() {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
return new DefaultStreamedContent();
}
else{
String imageId = context.getExternalContext().getRequestParameterMap().get("id");
Product product = getProductService().getProductById(Integer.parseInt(imageId));
return new DefaultStreamedContent(new ByteArrayInputStream(product.getProductImage()));
}
}
public ProductController() {
bean = new ProductBean();
}
public void setContent(StreamedContent content) {
this.content = content;
}
public UploadedFile getFile() {
return file;
}
public void setFile(UploadedFile file) {
this.file = file;
}
public void saveProduct(){
try{
Product product = new Product();
product.setProductImage(getFile().getContents());
getProductService().saveProduct(product);
file = null;
}
catch(Exception ex){
ex.printStackTrace();
}
}
public void validateFile(FacesContext ctx,
UIComponent comp,
Object value) {
List<FacesMessage> msgs = new ArrayList<FacesMessage>();
UploadedFile file = (UploadedFile)value;
int fileByte = file.getContents().length;
if(fileByte > 15360){
msgs.add(new FacesMessage("Too big must be at most 15KB"));
}
if (!(file.getContentType().startsWith("image"))) {
msgs.add(new FacesMessage("not an Image file"));
}
if (!msgs.isEmpty()) {
throw new ValidatorException(msgs);
}
}
}
добавьте эти строки кода в web.в XML
<filter>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>PrimeFaces FileUpload Filter</filter-name>
<servlet-name>Faces Servlet</servlet-name>
</filter-mapping>
и следующие файлы jar в WEBINF / lib папка.
commons-io-X.X and commons-fileupload-X.X, recommended most recent version.
commons-io-2.4,commons-io-2.4-javadoc,commons-io-2.4-sources,commons-io-2.4-tests,commons-io-2.4-test-sources,commons-fileupload-1.3,commons-fileupload-1.3-javadoc,commons-fileupload-1.3-sources,commons-fileupload-1.3-tests,commons-fileupload-1.3-test-sources
вид.в XHTML
<h:form id="ShowProducts">
<p:dataTable rowsPerPageTemplate="3,6,9" var="products" paginator="true" rows="3" emptyMessage="Catalog is empty" value="#{productController.bean.products}">
<p:column headerText="Product Name">
<p:graphicImage width="80" height="80" value="#{productController.content}">
<f:param name="id" value="#{products.productId}" />
</p:graphicImage>
#{products.productName}
</p:column>
</p:dataTable>
</h:form>