2012-07-16 95 views
7

我有一个视图范围的bean,我创建一个人。一个人可以有一张照片。这张照片上传到创建人的同一页面。图片没有存储在数据库或磁盘上(因为该人尚未创建)。该bean必须被视为作用域,因为可以在其他地方创建一个人,并使用相同的bean。如果bean是会话范围的,并且用户上传图片但不保存该人员,则该图片将在用户下次尝试创建人员时显示。在JSF中显示上传的图像

我使用两个bean解决了这个问题;一个视图范围的bean来创建人员和一个会话范围的bean来上传图片并将图片作为流。然而,这导致了上述问题。

如何以更好的方式解决这个问题?

上传豆:

@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(); 
    } 
} 

的创造,一个人的bean:

@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> 

回答

3

我已经走了不同的做法。我最初去显示上传的图像,但如果Person尚未创建,它似乎是一个更好的主意,保持它的所有客户端。我发现this question和创建以下基于所选答案:

在头我包括html5shiv如果浏览器是IE和用于兼容的版本低于9:

<h:outputText value="&lt;!--[if lt IE 9]&gt;" escape="false" /> 
<h:outputScript library="js" name="html5shiv.js" /> 
<h:outputText value="&lt;![endif]--&gt;" 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的魔力:

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; 
    } 
} 
+2

有趣的是,您在JSF中请求了一个示例,并以“Javascript/JQuery魔术”结尾。另外,你对另一个答案的评论不仅仅是一种选择,因为他的例子非常好。有很多JSF方法可以很好地完成你的任务 - 并且不需要在这里包含JS。你能否编辑你的问题或答案?问题和答案不一致。 – alexander 2015-02-23 11:58:31

+0

答案解决了我的问题,那么他们如何不合适?我还想指出,这个问题是在2012年7月16日,这是两年前。我可以放心地说,这个问题与我无关。如果我的答案有问题,可以编辑它。 ;-) – siebz0r 2015-02-23 12:51:38

3

Add.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> 

下面是Managed Bean的代码:

@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> 

并在WEBINF/lib文件夹中跟踪jar文件。

commons-io-X.X and commons-fileupload-X.X, recommended most recent version. 

公地-IO-2.4,公地-IO-2.4的Javadoc,公地-IO-2.4-源,公地-IO-2.4的测试中,公-IO-2.4 - 测试 - 源,公-fileupload-1.3,公地文件上传-1.3-的javadoc,公地文件上传-1.3-来源,公地文件上传-1.3的测试,公地文件上传-1.3测试来源

查看。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> 
+2

尽量保持你的例子简短。那里有很多代码是没有必要的。它只会让示例不易读。 – siebz0r 2013-06-09 15:59:16