2012-07-16 14 views
7

Ho un bean con ambito vista in cui creo una persona. Una persona può avere una foto. Questa immagine viene caricata nella stessa pagina in cui viene creata la persona. L'immagine non è memorizzata in un database o su disco (poiché la persona non è ancora stata creata). Il bean deve essere considerato con scope poiché una persona può essere creata altrove e utilizza lo stesso bean. Se il bean è a livello di sessione e un utente carica un'immagine ma non salva la persona, l'immagine verrà visualizzata al prossimo tentativo dell'utente di creare una persona.Visualizza immagine caricata in JSF

Ho risolto questo utilizzando due fagioli; un bean con scope vista per creare la persona e un bean con scope di sessione per caricare l'immagine e ottenere l'immagine come stream. Ciò tuttavia causa il problema annotato sopra.

Come posso risolvere questo in un modo migliore?

Il caricamento di fagioli:

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

Il Create-a-persona di fagioli:

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

La parte relativa pagina 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> 

risposta

3

sono andato per un diverso approccio. Inizialmente sono andato a visualizzare un'immagine caricata, tuttavia se lo Person non è ancora stato creato, mi è sembrata un'idea migliore quella di mantenere tutto il lato client. Ho trovato this question e creato il seguente basa sulla risposta scelta:

Nella testa includo html5shiv se il browser è IE e la versione è inferiore a 9 per la compatibilità:

<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" /> 

Per visualizzare/caricare il immagine che ho di questi elementi:

<p:fileUpload binding="#{upload}" mode="simple" 
    allowTypes="/(\.|\/)(gif|jpe?g|png)$/" 
    value="#{personBean.uploadedPicture}"/> 
<p:graphicImage value="#" height="150" binding="#{image}" /> 

e alcuni JavaScript/jQuery magia:

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}']")); 
    }); 

Il uploadedPicture proprietà è ora una semplice proprietà:

@ManagedBean(name = "personBean") 
@ViewScoped 
public class PersonBean 
{ 
    private UploadedFile uploadedPicture; 

    public UploadedFile getUploadedPicture() 
    { 
     return uploadedPicture; 
    } 

    public void setUploadedPicture(UploadedFile uploadedPicture) 
    { 
     this.uploadedPicture = uploadedPicture; 
    } 
} 
+2

E 'interessante, che lei ha chiesto un esempio nel JSF e si è conclusa con un po' "JavaScript/jQuery magica". Anche il tuo commento all'altra risposta è più che necassario, perché l'esempio di lui è abbastanza carino. Ci sono molti modi JSF per svolgere bene il tuo compito - e non c'è bisogno di includere JS qui. Puoi per favore modificare la tua domanda o risposta? Le domande e le risposte non vanno d'accordo. – alexander

+0

La risposta ha risolto il problema che avevo, quindi come si adattano? Vorrei anche precisare che la domanda è datata 16 luglio 2012, ovvero più di due anni fa. Posso tranquillamente dire che questa domanda è irrilevante per me. Se c'è qualcosa di sbagliato nella mia risposta, puoi modificarlo. ;-) – siebz0r

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> 

Qui è gestito Codice 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); 
     } 
    } 
} 

aggiungere queste righe di codice nel 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> 

E seguenti file jar nella cartella 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-test, commons-io-2.4-test-fonti, beni comuni -fileupload-1.3, commons-fileupload-1.3-javadoc, commons-FileUpload-1.3-sources, commons-FileUpload-1.3-test, commons-fileupload-1.3-test-sources

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

Cerca di mantenere i tuoi esempi brevi. C'è molto codice lì dentro che non è necessario. Rende solo l'esempio meno leggibile. – siebz0r