PrimeFaces p:fileUploadの使用方法 リスナーメソッドが呼び出されないか、UploadedFileがnull /エラーをスローする/使用できない


101

PrimeFacesを使用してファイルをアップロードしようとしていますがfileUploadListener、アップロードの完了後にメソッドが呼び出されません。

これがビューです:

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

そして豆:

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

}

メソッドにブレークポイントを設定しましたが、呼び出されたことはありません。mode="simple"and を使用するとajax="false"呼び出されますが、拡張モードで動作させたいです。NetbeansとGlassfish 3.1を使用しています。

回答:


224

構成およびトラブルシューティングの方法<p:fileUpload>は、PrimeFacesのバージョンによって異なります。

PrimeFacesのすべてのバージョン

以下の要件は、すべてのPrimeFacesバージョンに適用されます。

  1. enctype属性<h:form>をに設定する必要がありますmultipart/form-data。これがない場合、ajaxアップロードは機能する可能性がありますが、一般的なブラウザの動作は指定されておらず、フォームの構成とWebブラウザのmake / versionに依存しています。常に安全側に指定してください。

  2. mode="advanced"(つまりajaxアップロード、これがデフォルトです)を使用する場合<h:head>は、(マスター)テンプレートにあることを確認してください。これにより、必要なJavaScriptファイルが適切に含まれるようになります。これはmode="simple"(非Ajaxアップロード)には必要ありませんが、他のすべてのPrimeFacesコンポーネントのルックアンドフィールや機能を損なうため、とにかく見逃さないでください。

  3. 使用している場合mode="simple"(すなわち、非AJAXアップロード)、その後、アヤックスはどのPrimeFacesで無効にされなければならないことでボタン/リンクを命じるajax="false"、あなたが使用しなければならない<p:fileUpload value><p:commandButton action>の代わりに、<p:fileUpload fileUploadListener>(のためのPrimeFaces <=の7.x)または<p:fileUpload listener>(用PrimeFaces> = 8.x)の

したがって、ajaxサポート付きの(自動)ファイルアップロードが必要な場合(<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!
}

または、非Ajaxファイルのアップロードが必要な場合:

<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!
}

以下のようなAJAX関連の属性というノートを行いautoallowTypesupdateonstartoncomplete、などがされて無視さmode="simple"。したがって、そのような場合にそれらを指定する必要はありません。

また、後のHTTPリクエストによって呼び出された別のBeanメソッドではなく、上記のメソッド内でファイルの内容をすぐに読み取る必要あることに注意してください。これは、アップロードされたファイルのコンテンツがリクエストスコープであるため、後の/別のHTTPリクエストでは使用できないためです。後の要求でそれを読み取ろうとすると、おそらくjava.io.FileNotFoundException一時ファイルで終了します。


PrimeFaces 8.x

設定は以下の5.xバージョン情報と同じですが、リスナーが呼び出されない場合は、listener(8.xより前のバージョンのように)属性が呼び出されているかどうかを確認してくださいfileUploadListener

PrimeFaces 5.x

JSF 2.2を使用していて、faces-config.xmlJSF 2.2バージョンへの準拠も宣言されている場合は、追加の構成は必要ありません。PrimeFacesファイルアップロードフィルターはまったく必要ありません。使用するターゲットサーバーに応じてJSFを適切にインストールおよび構成する方法が不明な場合は、Mavenを介してJSFライブラリを適切にインストールおよび構成する方法に進んでください。そして私たちのJSFのwikiページのセクション「JSFのインストール」

ただし、JSF 2.2をまだ使用しておらず、それをアップグレードできない場合(Servlet 3.0互換コンテナにすでにある場合は、簡単に行うことができます)、以下のPrimeFacesファイルアップロードフィルターを手動で登録する必要がありますweb.xml(マルチを解析しますパーツリクエストを送信し、通常のリクエストパラメータマップに入力しFacesServletて、通常どおり作業を続行できるようにします。

<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>値は、同じのエントリのfacesServlet値と正確に一致する必要があります。したがって、たとえばの場合、それに合わせて編集する必要があります。<servlet>javax.faces.webapp.FacesServletweb.xmlFaces Servlet


PrimeFaces 4.x

PrimeFaces 5.xと同じストーリーが4.xにも適用されます。

によってアップロードされたファイルのコンテンツを取得する際に潜在的な問題のみがありますUploadedFile#getContents()。これはnull、Apache Commons FileUploadの代わりにネイティブAPIが使用されている場合に返されます。UploadedFile#getInputStream()代わりに使用する必要があります。MySQLでp:fileUploadからアップロードした画像をBLOBとして挿入する方法もご覧ください

ネイティブAPIのもう1つの潜在的な問題は、アップロードコンポーネントが、アップロードコンポーネントを処理しない別の「通常の」Ajaxリクエストが発生するフォームに存在する場合に現れます。「ファイルのアップロードがPrimeFaces 4.0 / JSF 2.2.xのAJAXで機能しない-javax.servlet.ServletException:リクエストコンテンツタイプがmultipart / form-dataではありません」も参照してください。

どちらの問題も、Apache Commons FileUploadに切り替えることで解決できます。詳細については、PrimeFaces 3.xのセクションを参照してください。


PrimeFaces 3.x

このバージョンは、JSF 2.2 /サーブレット3.0のネイティブファイルアップロードをサポートしていません。Apache Commons FileUploadを手動でインストールし、ファイルアップロードフィルターをに明示的に登録する必要がありますweb.xml

次のライブラリが必要です。

これらは、Webアプリケーションのランタイムクラスパスに存在する必要があります。Mavenを使用するときは、少なくともランタイムスコープであることを確認してください(デフォルトのコンパイルスコープも有効です)。JARを手動で持ち運ぶ場合は、JARが/WEB-INF/libフォルダーに入れられることを確認してください。

ファイルアップロードフィルターの登録の詳細は、上記のPrimeFaces 5.xセクションにあります。PrimeFaces 4+を使用していて、JSF 2.2 / Servlet 3.0ネイティブファイルアップロードの代わりにApache Commons FileUploadを明示的に使用したい場合は、上記のライブラリの横にある必要があり、以下のコンテキストパラメータもフィルタリングしますweb.xml

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

トラブルシューティング

それでも機能しない場合は、PrimeFacesの設定とは関係のない別の原因が考えられます。

  1. あなただけがPrimeFacesのファイルアップロードフィルタを使用している場合:別のはありますFilterあなたのWebアプリケーションで実行される前に、 PrimeFacesのファイルアップロードフィルタと、既に例えば、呼び出しによってリクエストボディを消費したgetParameter()getParameterMap()getReader()エトセトラ、。リクエストボディは一度しか解析できません。ファイルアップロードフィルターが機能する前にこれらのメソッドの1つを呼び出すと、ファイルアップロードフィルターは空のリクエスト本文を取得します。

    これを修正するに<filter-mapping>は、ファイルアップロードフィルタのの他のフィルタのに置く必要がありますweb.xml。リクエストがリクエストでない場合、multipart/form-dataファイルアップロードフィルターは何も起こらなかったかのように続行します。注釈を使用するために自動的に追加されるフィルター(PrettyFacesなど)を使用する場合、web.xmlを介して明示的な順序を追加する必要がある場合があります。WARでアノテーションを使用して実行のサーブレットフィルターの順序を定義する方法を参照してください

  2. PrimeFacesファイルアップロードフィルターを使用している場合のみ:FilterWebアプリには、PrimeFacesファイルアップロードフィルターのに実行され、RequestDispatcher#forward()呼び出しを実行した別のものがあります。通常、PrettyFacesなどのURL書き換えフィルターがこれを行います。これによりFORWARDディスパッチャーがトリガーされますが、フィルターはデフォルトでREQUESTディスパッチャーのみをリッスンします。

    これを修正するは、転送フィルターの前に PrimeFacesファイルアップロードフィルターを配置するか、FORWARDディスパッチャもリッスンするようにPrimeFacesファイルアップロードフィルターを再構成する必要があります。

    <filter-mapping>
        <filter-name>primeFacesFileUploadFilter</filter-name>
        <servlet-name>facesServlet</servlet-name>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>
  3. ネストされたがあり<h:form>ます。これはHTMLでは違法であり、ブラウザの動作は規定されていません。多くの場合、ブラウザは送信時に期待されるデータを送信しません。ネストしていないことを確認してください<h:form>。これは完全にフォームのに関係ありませんenctype。フォームをネストしないでください。

それでも問題が解決しない場合は、HTTPトラフィックをデバッグしてください。Webブラウザーの開発者ツールセットを開き(Chrome / Firebug23 + / IE9 +でF12を押します)、[ネット/ネットワーク]セクションを確認します。HTTP部分が正常に見える場合は、JSFコードをデバッグします。ブレークポイントを設定しFileUploadRenderer#decode()、そこから進みます。


アップロードしたファイルを保存しています

ようやくそれが機能するようになったら、次の質問はおそらく「アップロードされたファイルをどのように/どこに保存すればよいですか?」のようになります。さて、ここに続きます:アップロードされたファイルをJSFに保存する方法


2
別の原因web.xmlとしては、PrimeFacesユーザーガイドに従ってPrimeFacesアップロードフィルターを登録しなかったことが考えられます。とにかくそれを読みましたか?しかし、それはなぜmode="simple"あなたに役立つのかを説明しません。
BalusC、2012年

1
はい、私はそれを読み、フィルターを登録しましたが、サーバーの起動時にエラーが発生していることに気づきました "SEVERE:WebModule [/ EventsCalendary] PWC1270:Exception starting filter PrimeFaces FileUpload Filter"以前気づいた。このエラーを解決するためのヒントはありますか?
ロドリゴカバルカンテ2012年

2
フィルターのマッピングが正しくない可能性があります。それはにマッピングする必要がある<servlet-name>FacesServletあなたがdefiniedてきたようにweb.xml。ほとんどのIDE /コードジェネレーターではデフォルトFaces Servletでになっていますが、facesServlet命名規則をより確認しやすいものにすることもできます。
BalusC 2012年

2
commons-fileuploadをクラスパスとcommons-ioに追加することで解決しないでください。これらのライブラリが必要であると言っていることはありますか?とにかく、今はすべてが正常に機能しているようです。メソッドは本来の方法で呼び出されているので、ありがとうございます。
ロドリゴカバルカンテ2012年

1
したがって、TomEEとJBoss ..で同じ構成をAnt .. forum.primefaces.org/viewtopic.php?f=3&t=43798
Dmitry Alexandrov

30

あなたもプリティフェイスを使用していますか?次に、ディスパッチャーをFORWARDに設定します。

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

これは、OCP Rewriteと一緒に使用した場合でも問題になります。私はあなたにビールを借りています:)
Babl

7

Primefaces 3.4とNetbeans 7.2で気付いた1つのポイント:

関数handleFileUpload、つまり(イベント)のNetbeans自動入力パラメータを削除します。そうしないと、イベントがnullになる可能性があります。

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


0

プライムフェイス5.3でも同じ問題が発生し、BalusCで説明されているすべてのポイントを調べましたが、結果はありませんでした。私はFileUploadRenderer#decode()をデバッグするという彼のアドバイスに従いましたが、私のweb.xmlが不適切に設定されていることを発見しました

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

param-valueはこれらの3つの値の1つでなければなりませんが、すべてではありません!! context-paramセクション全体を削除できます。デフォルトはautoです。


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パブリッククラスSubmissionはSerializable {

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>

これが答えである理由を説明できますか?これはコードであり、説明などではありません
Kukeltje

"#{bean.uploadFile}"と "#{bean.uploadFasta}"を比較し、update = "messages"を削除すると、(それだけで)機能します。
ロムスキー

0

ここでの提案はどちらも役に立ちませんでした。だから私はprimefacesをデバッグしなければならず、問題の理由は次のとおりであることがわかりました:

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

次に、web.xmlのFacesサーブレットにセクションを追加しました。これで問題が解決しました:

<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

この投稿に記載されているすべての構成があるため、同じ問題がありましたが、私の場合は、2つのjqueryインポート(そのうちの1つはprimefacesのクエリ)があり、ファイルのアップロードで競合が発生したためです。

Primefaces Jqueryの競合を参照してください


ブラウザの開発者コンソールで特定のエラーが発生しませんでしたか?
Kukeltje、2017年

@Kukeltjeこれはコンソールに表示されたものです:Uncaught TypeError:Object [object Object] has no method 'fileupload'
Christian Altamirano Ayala

0

TomeeまたはTomcatを使用していて機能しない場合は、META-INFでcontext.xmlを作成して、allowCasualMultipartParsing = "true"を追加してください。

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

これは、間違ったフィルター構成/順序の回避策です。
BalusC

こんにちは@BalusC、もっと説明してくれませんか?この回避策よりも良い方法はありますか?
ザビエルランブロス

この質問の私の回答をご覧ください。
BalusC

0

JBoss 7.2(Undertow)およびPrimeFaces 6.0では、org.primefaces.webapp.filter.FileUploadFilterをweb.xmlから削除し、コンテキストパラメータファイルアップローダーをネイティブに設定する必要があります。

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

すべきか そうでない場合、特定のエラーが発生しますか?
Kukeltje

はい、この変更がないと、FileUploadEventは呼び出されません。
Alex D

これは明示的なエラーではなく、予期しない動作です
Kukeltje
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.