PrimeFaces p: fileUpload nasıl kullanılır? Dinleyici yöntemi hiçbir zaman çağrılmaz veya UploadedFile boştur / bir hata atar / kullanılamaz


101

PrimeFaces kullanarak bir dosya yüklemeye çalışıyorum, ancak fileUploadListeneryöntem yükleme bittikten sonra çalıştırılmıyor.

İşte manzara:

<h:form>
    <p:fileUpload fileUploadListener="#{fileUploadController.handleFileUpload}"
        mode="advanced" 
        update="messages"
        sizeLimit="100000" 
        allowTypes="/(\.|\/)(gif|jpe?g|png)$/"/>

    <p:growl id="messages" showDetail="true"/>
</h:form>

Ve fasulye:

@ManagedBean
@RequestScoped
public class FileUploadController {

    public void handleFileUpload(FileUploadEvent event) {
        FacesMessage msg = new FacesMessage("Succesful", event.getFile().getFileName() + " is uploaded.");
        FacesContext.getCurrentInstance().addMessage(null, msg);
    }

}

Yönteme bir kesme noktası yerleştirdim, ancak hiç çağrılmadı. Kullanırken mode="simple"ve ajax="false"bu çağrılan, ama gelişmiş modda çalışmak istiyorum be. Netbeans ve Glassfish 3.1 kullanıyorum.

Yanıtlar:


226

Yapılandırma ve sorun giderme işlemleri <p:fileUpload>PrimeFaces sürümüne bağlıdır.

Tüm PrimeFaces sürümleri

Aşağıdaki gereksinimler tüm PrimeFaces sürümleri için geçerlidir:

  1. enctypeÖznitelik <h:form>ihtiyaçlarına ayarlanmalıdır multipart/form-data. Bu olmadığında, ajax yüklemesi sadece çalışabilir, ancak genel tarayıcı davranışı belirtilmez ve form kompozisyonuna ve web tarayıcısı marka / sürümüne bağlıdır. Her zaman güvenli tarafta olmasını belirtin.

  2. Kullanırken mode="advanced"(yani ajax yüklemesi, bu varsayılandır), ardından <h:head>(ana) şablonda bir tane bulunduğundan emin olun . Bu, gerekli JavaScript dosyalarının düzgün bir şekilde dahil edilmesini sağlayacaktır. Bu, mode="simple"(ajax dışı yükleme) için gerekli değildir , ancak bu, diğer tüm PrimeFaces bileşenlerinin görünüşünü ve işlevselliğini bozacaktır, bu yüzden yine de bunu kaçırmak istemezsiniz.

  3. Kullanırken mode="simple"(yani ajax dışı yükleme), o zaman ajax herhangi bir PrimeFaces komut düğmesinde / bağlantılarında tarafından devre dışı bırakılmalıdır ajax="false"ve (PrimeFaces <= 7.x için) veya (PrimeFaces> = 8.x için ) yerine <p:fileUpload value>with <p:commandButton action>kullanmalısınız.<p:fileUpload fileUploadListener><p:fileUpload listener>

Yani, ajax desteğiyle (otomatik) dosya yüklemek istiyorsanız (aklınızda bulundurun <h:head>!):

<h:form enctype="multipart/form-data">
    <p:fileUpload fileUploadListener="#{bean.upload}" auto="true" /> // for PrimeFaces >= 8.x this should be listener instead of fileUploadListener 
</h:form>
public void upload(FileUploadEvent event) {
    UploadedFile uploadedFile = event.getFile();
    String fileName = uploadedFile.getFileName();
    String contentType = uploadedFile.getContentType();
    byte[] contents = uploadedFile.getContents(); // Or getInputStream()
    // ... Save it, now!
}

Veya ajax dışı dosya yüklemek istiyorsanız:

<h:form enctype="multipart/form-data">
    <p:fileUpload mode="simple" value="#{bean.uploadedFile}" />
    <p:commandButton value="Upload" action="#{bean.upload}" ajax="false" />
</h:form>
private UploadedFile uploadedFile; // +getter+setter

public void upload() {
    String fileName = uploadedFile.getFileName();
    String contentType = uploadedFile.getContentType();
    byte[] contents = uploadedFile.getContents(); // Or getInputStream()
    // ... Save it, now!
}

Gibi ajax ilgili özelliklerin o notu mı auto, allowTypes, update, onstart, oncomplete, vb edilir ihmal içinde mode="simple". Yani böyle bir durumda bunları belirtmeye gerek yok.

Ayrıca , daha sonraki bir HTTP isteği tarafından başlatılan farklı bir Bean yönteminde değil, yukarıda belirtilen yöntemlerin hemen içindeki dosya içeriğini okumanız gerektiğini unutmayın . Bunun nedeni, yüklenen dosya içeriğinin istek kapsamlı olması ve dolayısıyla daha sonraki / farklı bir HTTP isteğinde kullanılamamasıdır. Daha sonraki bir talepte okumaya yönelik herhangi bir girişim, büyük olasılıkla java.io.FileNotFoundExceptiongeçici dosyada sonuçlanacaktır .


PrimeFaces 8.x

Yapılandırma aşağıdaki 5.x sürüm bilgisiyle aynıdır, ancak dinleyiciniz çağrılmazsa, öznitelik çağrılıp çağrılmadığını kontrol edin listener(8.x öncesi sürümlerde olduğu gibi)fileUploadListener

PrimeFaces 5.x

JSF 2.2 kullanıyorsanız ve sizin faces-config.xmlde JSF 2.2 sürümüne uygun olduğu bildirilmişse, bu herhangi bir ek yapılandırma gerektirmez . PrimeFaces dosya yükleme filtresine hiç ihtiyacınız yoktur. Kullanılan hedef sunucuya bağlı olarak JSF'yi nasıl doğru bir şekilde kurup yapılandıracağınız konusunda net değilseniz, JSF kitaplıkları Maven aracılığıyla nasıl düzgün şekilde kurulur ve yapılandırılır? ve JSF wiki sayfamızın "JSF Kurulumu" bölümü .

Ancak henüz JSF 2.2 kullanmıyorsanız ve yükseltemiyorsanız (zaten Servlet 3.0 uyumlu bir konteyner üzerindeyken zahmetsiz olmalıdır), aşağıdaki PrimeFaces dosya yükleme filtresini manuel olarak kaydetmeniz gerekir web.xml(çoklu parça isteği ve normal istek parametre haritasını doldurun, böylece FacesServlether zamanki gibi çalışmaya devam edebilir):

<filter>
    <filter-name>primeFacesFileUploadFilter</filter-name>
    <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>primeFacesFileUploadFilter</filter-name>
    <servlet-name>facesServlet</servlet-name>
</filter-mapping>

<servlet-name>Değeri facesServlettam olarak değerle aynı olmalıdır <servlet>girişinde javax.faces.webapp.FacesServletaynı yer web.xml. Öyleyse örneğin ise Faces Servlet, eşleşecek şekilde düzenlemeniz gerekir.


PrimeFaces 4.x

PrimeFaces 5.x ile aynı hikaye 4.x için de geçerlidir.

Yalnızca yüklenen dosya içeriğinin tarihine kadar alınmasında olası bir sorun var UploadedFile#getContents(). Bu null, Apache Commons FileUpload yerine yerel API kullanıldığında geri dönecektir . Bunun UploadedFile#getInputStream()yerine kullanmanız gerekir . Ayrıca bkz. MySQL'de p: fileUpload'dan BLOB olarak yüklenen görüntü nasıl eklenir?

Yerel API ile ilgili diğer bir olası sorun, yükleme bileşeninin, yükleme bileşenini işlemeyen farklı bir "normal" ajax isteğinin tetiklendiği bir formda mevcut olmasıdır. Ayrıca bkz. Dosya yükleme, PrimeFaces 4.0 / JSF 2.2.x'te AJAX ile çalışmıyor - javax.servlet.ServletException: İstek içerik türü çok parçalı / form verisi değil .

Her iki sorun da Apache Commons FileUpload'a geçilerek çözülebilir. Ayrıntılı bilgi için PrimeFaces 3.x bölümüne bakın.


PrimeFaces 3.x

Bu sürüm JSF 2.2 / Servlet 3.0 yerel dosya yüklemesini desteklemez. Apache Commons FileUpload'u manuel olarak yüklemeniz ve dosya yükleme filtresini içinde açıkça kaydetmeniz gerekir web.xml.

Aşağıdaki kitaplıklara ihtiyacınız var:

Bunlar web uygulamasının çalışma zamanı sınıf yolunda mevcut olmalıdır. Maven'i kullanırken, en azından çalışma zamanı kapsamlı olduklarından emin olun (varsayılan derleme kapsamı da iyidir). JAR'ları elle taşırken, /WEB-INF/libklasörde son bulduklarından emin olun .

Dosya yükleme filtresi kayıt ayrıntıları, yukarıdaki PrimeFaces 5.x bölümünde bulunabilir. PrimeFaces 4+ kullanıyorsanız ve JSF 2.2 / Servlet 3.0 yerel dosya yüklemesi yerine Apache Commons FileUpload kullanmak istiyorsanız, söz konusu kitaplıkların yanında ve aşağıdaki bağlam parametresini de filtrelemeniz gerekir web.xml:

<context-param>
    <param-name>primefaces.UPLOADER</param-name>
    <param-value>commons</param-value><!-- Allowed values: auto, native and commons. -->
</context-param>

Sorun giderme

Hala çalışmıyorsa, PrimeFaces yapılandırmasıyla ilgili olmayan başka olası nedenler şunlardır:

  1. Eğer PrimeFaces dosya yükleme filtre kullanıyorsanız Sadece eğer: bir tane daha var Filterçalıştığı için webapp önce PrimeFaces dosya yükleme filtre ve zaten örneğin arayarak istek gövdesini tükettiği getParameter(), getParameterMap(), getReader(), vesaire. Bir istek gövdesi yalnızca bir kez ayrıştırılabilir. Dosya yükleme filtresi işini yapmadan önce bu yöntemlerden birini çağırdığınızda, dosya yükleme filtresi boş bir istek gövdesi alır.

    Bunu düzeltmek için <filter-mapping>, dosya yükleme filtresini diğer filtreden önce yerleştirmeniz gerekir web.xml. İstek bir multipart/form-dataistek değilse , dosya yükleme filtresi hiçbir şey olmamış gibi devam edecektir. Ek açıklamalar kullandıkları için otomatik olarak eklenen filtreler kullanırsanız (örn. PrettyFaces), web.xml aracılığıyla açık sıralama eklemeniz gerekebilir. WAR'da ek açıklamaları kullanarak yürütme için servlet filtre sırasını tanımlama bölümüne bakın.

  2. Yalnızca PrimeFaces dosya yükleme filtresini kullanıyorsanız: Web uygulamanızda PrimeFaces dosya yükleme filtresinden önceFilter çalışan ve bir arama gerçekleştiren başka bir uygulama vardır . PrettyFaces gibi URL yeniden yazma filtreleri bunu genellikle yapar. Bu, dağıtıcıyı tetikler , ancak filtreler varsayılan olarak yalnızca dağıtıcıda dinler .RequestDispatcher#forward()FORWARDREQUEST

    Bunu düzeltmek için, PrimeFaces dosya yükleme filtresini yönlendirme filtresinin önüne koymanız veya FORWARDdağıtıcıda dinlemek için PrimeFaces dosya yükleme filtresini yeniden yapılandırmanız gerekir :

    <filter-mapping>
        <filter-name>primeFacesFileUploadFilter</filter-name>
        <servlet-name>facesServlet</servlet-name>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>
  3. İç içe bir var <h:form>. Bu HTML'de yasa dışıdır ve tarayıcı davranışı belirtilmemiştir. Çoğu zaman, tarayıcı gönderildiğinde beklenen verileri göndermez. Yuvalanmadığınızdan emin olun <h:form>. Bu tamamen formdan bağımsızdır enctype. Sadece formları hiç iç içe geçirmeyin.

Hala sorun yaşıyorsanız, HTTP trafiğinde hata ayıklayın. Web tarayıcısının geliştirici araç setini açın (Chrome / Firebug23 + / IE9 + 'da F12'ye basın) ve Net / Network bölümünü kontrol edin. HTTP kısmı iyi görünüyorsa, JSF kodunda hata ayıklayın. Bir kesme noktası koyun FileUploadRenderer#decode()ve oradan ilerleyin.


Yüklenen dosyayı kaydetme

Sonunda onu çalıştırdıktan sonra, sonraki sorunuz muhtemelen "Yüklenen dosyayı nasıl / nereye kaydederim?" Gibi olacaktır. Peki, buradan devam edin: Yüklenen dosya JSF'ye nasıl kaydedilir .


2
Diğer bir neden web.xml, PrimeFaces Kullanıcı Kılavuzuna göre PrimeFaces yükleme filtresini kaydetmemiş olmanız olabilir . Yine de okudun mu? Ancak bu, neden mode="simple"sizin için işe yaradığını açıklamaz .
BalusC

1
Evet okudum ve filtreyi kaydettim, ancak sunucuyu başlatırken bunun bana bir hata verdiğini fark ettim: "SEVERE: WebModule [/ EventsCalendary] PWC1270: İstisna başlatma filtresi PrimeFaces FileUpload Filtresi" Kendimi çok aptal hissediyorum daha önce fark ettim. Bu hatayı çözmek için herhangi bir ipucu var mı?
Rodrigo Cavalcante

2
Belki de filtre eşlemesi yanlıştır. Bu üzerinde haritasının çıkarılması <servlet-name>arasında FacesServletiçeri definied ettik web.xml. Çoğu IDE / kod oluşturucu tarafından varsayılan olarak ayarlanmıştır Faces Servlet, ancak bu kadar iyi facesServletveya adlandırma kurallarını daha onaylayan bir şey de olabilir.
BalusC

2
Sınıf yoluna ortak dosya yükleme ve ortak dosya yükleme ekleyerek bunu asla çözmedi, bu kitaplıklara ihtiyaç olduğunu söyleyen herhangi bir yer var mı? Her neyse, şu anda her şey çalışıyor gibi görünüyor, yöntem olması gerektiği gibi çağrılıyor, teşekkürler.
Rodrigo Cavalcante

1
Böylece hepsi TomEE ve JBoss'ta aynı yapılandırmayı düşündüğüm duruma geldi .. forum.primefaces.org/viewtopic.php?f=3&t=43798
Dmitry Alexandrov

30

Sen de güzel yüzler mi kullanıyorsun? Ardından, dağıtıcıyı İLERİ olarak ayarlayın:

<filter-mapping>
   <filter-name>PrimeFaces FileUpload Filter</filter-name>
   <servlet-name>Faces Servlet</servlet-name>
   <dispatcher>FORWARD</dispatcher>
</filter-mapping>

Bu, OCP Yeniden Yazma ile kullanıldığında hala bir sorundur. Sana bir bira borçluyum :)
Babl

7

Primefaces 3.4 ve Netbeans 7.2 ile fark ettiğim bir nokta:

HandleFileUpload yani (olay) işlevi için Netbeans otomatik doldurulan parametrelerini kaldırın, aksi takdirde olay boş olabilir.

<h:form>
    <p:fileUpload fileUploadListener="#{fileUploadController.handleFileUpload(event)}"
        mode="advanced" 
        update="messages"
        sizeLimit="100000" 
        allowTypes="/(\.|\/)(gif|jpe?g|png)$/"/>

    <p:growl id="messages" showDetail="true"/>
</h:form>

2

Görünüşe göre javax.faces.SEPARATOR_CHAR, _ değerine eşit olmamalıdır


2
Biraz detaylandırır mısınız lütfen ?!
Karl Richter

0

Primefaces 5.3 ile aynı sorunu yaşadım ve BalusC tarafından açıklanan tüm noktaların üzerinden hiçbir sonuç alınamadı. FileUploadRenderer # decode () hata ayıklama tavsiyesine uydum ve web.xml dosyamın düzgün ayarlanmamış olduğunu keşfettim

<context-param>
  <param-name>primefaces.UPLOADER</param-name>
  <param-value>auto|native|commons</param-value>
</context-param>

Param-değeri bu 3 değerden 1'i olmalı ama hepsi değil !! Bağlam parametresinin tamamı kaldırılabilir ve varsayılan otomatik olacaktır


0

bean.xhtml

    <h:form enctype="multipart/form-data">    
<p:outputLabel value="Choose your file" for="submissionFile" />
                <p:fileUpload id="submissionFile"
                    value="#{bean.file}"
                    fileUploadListener="#{bean.uploadFile}" mode="advanced"
                    auto="true" dragDropSupport="false" update="messages"
                    sizeLimit="100000" fileLimit="1" allowTypes="/(\.|\/)(pdf)$/" />

</h:form>

Bean.java

@ManagedBean

@ViewScoped public class Submission, Serializable'ı uygular {

private UploadedFile file;

//Gets
//Sets

public void uploadFasta(FileUploadEvent event) throws FileNotFoundException, IOException, InterruptedException {

    String content = IOUtils.toString(event.getFile().getInputstream(), "UTF-8");

    String filePath = PATH + "resources/submissions/" + nameOfMyFile + ".pdf";

    MyFileWriter.writeFile(filePath, content);

    FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
            event.getFile().getFileName() + " is uploaded.", null);
    FacesContext.getCurrentInstance().addMessage(null, message);

}

}

web.xml

    <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<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>

Bunun neden bir cevap olduğunu açıklayabilir misin? Bu sadece bir kod, açıklama ya da her neyse
Kukeltje

"# {bean.uploadFile}" ve "# {bean.uploadFasta}", update = "mesajlarını" kaldırın ve (yalnızca) benim için çalışacaktır!
romsky

0

Buradaki önerilerin hiçbiri bana yardımcı olmadı. Bu yüzden ilkel karakterlerde hata ayıklamak zorunda kaldım ve sorunun nedenini buldum:

java.lang.IllegalStateException: No multipart config for servlet fileUpload

Sonra web.xml'deki yüzler sunucu uygulamasına bölüm ekledim. Böylece sorunu çözdü:

<servlet>
    <servlet-name>main</servlet-name>

        <servlet-class>org.apache.myfaces.webapp.MyFacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
        <multipart-config>
            <location>/tmp</location>
            <max-file-size>20848820</max-file-size>
            <max-request-size>418018841</max-request-size>
            <file-size-threshold>1048576</file-size-threshold>
        </multipart-config>
    </servlet>

0

Bu yazıda açıklanan tüm yapılandırmaya sahip olduğum için aynı sorunu yaşadım, ancak benim durumumda iki jquery içe aktarmam (bunlardan biri primefaces'in sorgusuydu) nedeniyle çatışmaların dosya yüklemesine neden oldu.

Primefaces Jquery çakışmasına bakın


O zaman tarayıcı geliştirici konsolunda belirli bir hata almadınız mı?
Kukeltje

@Kukeltje, konsolun gösterdiği şey bu: Yakalanmamış TypeError: Object [object Object] 'dosya yükleme' yöntemine sahip değil
Christian Altamirano Ayala

0

Tomee veya Tomcat kullanan ve çalışmasını sağlayamayan kişiler için oluşturmaya çalışın , META- INF'de context.xml ve allowCasualMultipartParsing = "true" ekleyin

<?xml version="1.0" encoding="UTF-8"?>
<Context allowCasualMultipartParsing="true">
  <!-- empty or not depending your project -->
</Context>

Bu, yanlış filtre yapılandırması / sıralaması için bir geçici çözümdür.
BalusC

Merhaba @BalusC, bize daha fazla açıklama verebilir misiniz? Bu çalışmanın daha iyi bir yolu var mı?
Xavier Lambros

Bu soruda cevabımı görün.
BalusC

0

JBoss 7.2 (Undertow) ve PrimeFaces 6.0 ile org.primefaces.webapp.filter.FileUploadFilter web.xml'den kaldırılmalı ve bağlam param dosyası yükleyicisi yerel olarak ayarlanmalıdır:

<context-param>
    <param-name>primefaces.UPLOADER</param-name>
    <param-value>native</param-value>
</context-param>

Meli? Yapmazsanız belirli hatalar alıyor musunuz ?
Kukeltje

Evet, FileUploadEvent'im bu değişiklikler olmadan başlatılmaz.
Alex D

Bu açık bir hata değil, beklenmedik bir davranış
Kukeltje
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.