【发布时间】:2013-12-18 11:23:08
【问题描述】:
大家好,
我正在使用 primefaces 4 和 Tomcat 7。我希望用户能够上传多个图像并在将这些图像写入磁盘之前立即查看每个上传的图像(当它们在内存中时)。图像只会在表单提交后写入磁盘。我正在使用 p:fileUpload 组件。
以下是相关代码:
...
<p:tab id="imageTab" title="#{msgs.images}">
<p:dataGrid id="imagesDataGrid" columns="4" value="#{modifyProductAdminBean.imageIds}"
var="imgId" >
<p:graphicImage value="#{pA_ImageService.image}" >
<f:param name="id" value="#{imgId}" />
</p:graphicImage>
</p:dataGrid>
<p:fileUpload fileUploadListener="#{modifyProductAdminBean.handleFileUpload}" mode="advanced"
dragDropSupport="true" multiple="true" sizeLimit="5242880"
invalidFileMessage="#{msgs.invalidFileType}"
invalidSizeMessage="#{msgs.fileTooLarge}"
allowTypes="/(\.|\/)(gif|jpe?g|png|jpg)$/"
cancelLabel="#{msgs.cancel}"
uploadLabel="#{msgs.upload}"
label="#{msgs.choose}"
update="imagesDataGrid" />
</p:tab>
...
@ManagedBean
@ViewScoped
public class ModifyProductAdminBean implements Serializable {
private Map<String, UploadedFile> uploadedImages;
public void handleFileUpload(FileUploadEvent event) {
UploadedFile file = event.getFile();
String uniqueId = UUID.randomUUID().toString();
this.getUploadedImages().put(uniqueId, file);
}
public Set<String> getImageIds() {
return this.getUploadedImages().keySet();
}
public Map<String, UploadedFile> getUploadedImages() {
return uploadedImages;
}
...
}
@ManagedBean
@ApplicationScoped
public class PA_ImageService implements Serializable {
private final ModifyProductAdminBean modifyProductAdminBean;
public PA_ImageService() {
this.modifyProductAdminBean = BeanManager.findBean("modifyProductAdminBean");
}
// Taken from http://stackoverflow.com/questions/8207325/display-image-from-database-with-pgraphicimage
public StreamedContent getImage() {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
// So, we're rendering the HTML. Return a stub StreamedContent so that it will generate right URL.
return new DefaultStreamedContent();
} else {
// So, browser is requesting the image. Return a real StreamedContent with the image bytes.
String imageId = context.getExternalContext().getRequestParameterMap().get("id");
// remove [, ] characters between
imageId = imageId.substring(1, imageId.length() - 1);
UploadedFile uFile = this.modifyProductAdminBean.getUploadedImages().get(imageId);
return new DefaultStreamedContent(new ByteArrayInputStream(uFile.getContents()));
}
}
...
}
public class BeanManager implements Serializable {
@SuppressWarnings("unchecked")
public static <T> T findBean(String beanName) {
FacesContext context = FacesContext.getCurrentInstance();
return (T) context.getApplication().evaluateExpressionGet(context, "#{" + beanName + "}", Object.class);
}
...
}
当我运行此代码时,我在“PA_ImageService”的最后一行收到 NullPointerException(返回新的 ...)。更准确地说,虽然 uFile 不为 null,但“uFile.getContents()”返回 null。为什么?我做错了什么?
我观察到的更多细节:
我注意到,当我上传文件时,Tomcat 将其临时存储在 E:\Program Files (x86)\Apache Software Foundation\Apache Tomcat 7.0.41\work\Catalina\localhost\MyProject 目录中的 .tmp 文件中。
通过调试项目,我可以看到:当我到达PA_ImageService的if (context... == PhaseId.RENDER_RESPONSE)行时,.tmp文件仍然存在。但是,在getImage()方法的第二次访问中,当控件移动到else块时,我可以看到tmp文件不再存在。因此,无法检索其内容,因此无法检索 null 结果。
对这是如何发生的有任何想法吗?
【问题讨论】:
-
我在这个问题的末尾添加了额外的观察。请看一下,如果你能帮上忙,请告诉我!谢谢
标签: jsf file-upload primefaces