2012-07-16 19 views
7

Mam widok z określonymi komponentami, w których utworzę osobę. Osoba może mieć zdjęcie. To zdjęcie zostało przesłane na tę samą stronę, na której osoba została utworzona. Obraz nie jest przechowywany w bazie danych lub na dysku (ponieważ ta osoba nie jest jeszcze utworzona). Komponent bean musi mieć zasięg widoku, ponieważ dana osoba może zostać utworzona gdzie indziej, a ta używa tego samego komponentu bean. Jeśli komponent bean ma zasięg sesji, a użytkownik przesyła obraz, ale nie zapisuje osoby, zdjęcie zostanie wyświetlone następnym razem, gdy użytkownik spróbuje utworzyć osobę.Wyświetlenie przesłanego obrazu w JSF

Rozwiązałem to, używając dwóch ziaren; jeden widok z określonymi komponentami, aby utworzyć osobę i komponent o rozmiarze sesji, aby przesłać obraz i uzyskać obraz jako strumień. Powoduje to jednak problem opisany powyżej.

Jak mogę rozwiązać ten problem w lepszy sposób?

Wysyłanie fasola:

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

Fasola kreacji osobę:

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

Właściwa część stronę 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> 

Odpowiedz

3

Poszedłem do innego podejście. Początkowo zdecydowałem się na wyświetlanie przesłanego obrazu, jednak jeśli nie został jeszcze utworzony Person, lepszym rozwiązaniem było utrzymanie go po stronie klienta. Znalazłem this question i stworzył następuje na podstawie wybranej odpowiedzi:

W głowie mi to html5shiv jeśli przeglądarka jest IE a wersja jest mniej niż 9 kompatybilności:

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

Aby wyświetlić/upload obraz mam te elementy:

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

a niektóre 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 właściwość jest teraz proste nieruchomości:

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

    public UploadedFile getUploadedPicture() 
    { 
     return uploadedPicture; 
    } 

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

Ciekawe, że poprosiłeś o przykład w JSF i skończyłeś z "magią JavaScript/JQuery". Również twój komentarz do drugiej odpowiedzi jest więcej niż konieczny, ponieważ jego przykład jest całkiem niezły. Istnieje wiele sposobów JSF, które wykonują twoje zadanie całkiem dobrze i nie ma potrzeby dołączania JS tutaj. Czy możesz edytować swoje pytanie lub odpowiedź? Pytanie i odpowiedź nie pasują do siebie. – alexander

+0

Odpowiedź rozwiązała problem, który miałem, więc jak one nie pasują do siebie? Chciałbym również powiedzieć, że pytanie pochodzi z 16 lipca 2012 roku, czyli ponad dwa lata temu. Mogę śmiało powiedzieć, że to pytanie jest dla mnie nieistotne. Jeśli coś jest nie tak z moją odpowiedzią, możesz ją edytować. ;-) – 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> 

Tutaj jest kod zarządzany 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); 
     } 
    } 
} 

Dodaj te linie kodu w internecie. 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> 

I następujące pliki JAR w folderze WEBINF/lib.

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

fotografia-io-2,4, fotografia-io-2,4-javadoc, fotografia-io-2,4-źródeł, fotografia-io-2,4 Testy fotografia-io-2,4-test-źródła, fotografia -fileupload-1,3, commons-FileUpload-1,3-javadoc, commons-FileUpload-1,3-sources-commons FileUpload-1,3-testy, commons-FileUpload-1,3-test-sources

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

Staraj się, aby Twoje przykłady były krótkie. Tam jest dużo kodu, który nie jest konieczny. To sprawia, że ​​przykład jest mniej czytelny. – siebz0r