[解決済み] PrimeFaces p:fileUploadを使うには?リスナーメソッドが呼び出されない、またはUploadedFileがNullである / エラーが発生する / 使えない
質問内容
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"
と
ajax="false"
で、呼び出されるのですが、アドバンスドモードで動作させたいのです。私はNetbeansとGlassfish 3.1を使っています。
どのように解決するのですか?
設定方法とトラブルシューティング
<p:fileUpload>
は、PrimeFacesとJSFのバージョンに依存します。
すべてのPrimeFacesのバージョン
以下の要件は、すべてのPrimeFacesのバージョンに適用されます。
-
以下の
enctype
の属性は<h:form>
を設定する必要があります。multipart/form-data
. これがない場合、ajaxによるアップロードはうまくいくかもしれませんが、一般的なブラウザの動作は、フォームの構成やウェブブラウザのメーカー/バージョンに依存し、不特定多数になります。念のため、必ず指定してください。 -
を使用する場合
mode="advanced"
(すなわち ajax アップロード、これはデフォルトです) を使用する場合は、必ず<h:head>
を (マスター) テンプレートに追加してください。これにより、必要な JavaScript ファイルが適切にインクルードされます。の場合は必要ありません。mode="simple"
(非ajaxアップロード)では必要ありませんが、これは他のすべてのPrimeFacesコンポーネントのルックアンドフィールと機能を壊すことになるので、いずれにせよ見逃したくはないでしょう。 -
を使用する場合
mode="simple"
(すなわち非ajaxアップロード)を使用している場合、PrimeFacesコマンドボタン/リンクのajaxを以下のように無効化する必要があります。ajax="false"
によって、PrimeFacesのコマンドボタンやリンクでjaxを無効にしなければなりません。<p:fileUpload value>
と共に<p:commandButton action>
の代わりに<p:fileUpload listener>
.
ですから、もしあなたがajaxサポートで(自動)ファイルアップロードをしたいのであれば(
<h:head>
!):
<h:form enctype="multipart/form-data">
<p:fileUpload listener="#{bean.upload}" auto="true" /> // For PrimeFaces version older than 8.x this should be fileUploadListener instead of listener.
</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 transient 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に関連する属性があることに注意してください。
auto
,
allowTypes
,
update
,
onstart
,
oncomplete
などは
は無視されます。
で
mode="simple"
. なので、このような場合は指定する必要はありません。
また、注意点として
ファイルの中身をすぐに読む
を行う必要があることに注意してください。これはアップロードされたファイルの内容がリクエストスコープされているため、後の/異なるHTTPリクエストで利用できないからです。後のリクエストでそれを読み込もうとすると、ほとんどの場合
java.io.FileNotFoundException
になってしまいます。
PrimeFaces 8.x
設定は以下の5.xバージョンの情報と同じですが、リスナーが呼び出されない場合は、method属性が呼び出されているかどうかを確認します。
listener
となっているか、また、(8.x以前のバージョンと同じように)メソッド属性が
fileUploadListener
.
PrimeFaces 5.x
これは
ではなく
は、JSF 2.2 を使っていて、かつ
faces-config.xml
が JSF 2.2 バージョンに適合していることを宣言している場合。あなたは
ではなく
はPrimeFacesのファイルアップロードフィルタを全く必要とせず、さらに
ではなく
が必要です。
primefaces.UPLOADER
のコンテキストパラメータが必要です。
web.xml
. 使用するターゲットサーバーに応じて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.FacesServlet
の中で、同じ
web.xml
. ですから、もしそれが例えば
Faces Servlet
であれば、それに合うように編集する必要があります。
PrimeFaces 4.x
PrimeFaces 5.xと同じ話が4.xにも当てはまります。
によってアップロードされたファイルの内容を取得する際に、潜在的な問題があるだけです。
UploadedFile#getContents()
. これは
null
のように、Apache Commons FileUpload ではなく、ネイティブ API を使用した場合です。この場合
UploadedFile#getInputStream()
を使う必要があります。また
p:fileUploadからアップロードされた画像をMySQLのBLOBとして挿入するにはどうすればよいですか?
ネイティブ API の別の潜在的な問題は、アップロード コンポーネントを処理しない別の "regular" 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 / Servlet 3.0 のネイティブファイルアップロードはサポートされていません。Apache Commons FileUploadを手動でインストールし、ファイルアップロードフィルタを明示的に
web.xml
.
以下のライブラリが必要です。
これらはウェブアプリケーションのランタイムクラスパスに存在しなければなりません。Maven を使用する場合、これらが少なくとも実行時のスコープであることを確認してください (デフォルトのコンパイルのスコープもよいです)。手動で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の設定とは関係なく考えられる別の原因を紹介します。
-
PrimeFacesのファイルアップロードフィルタを使用している場合のみです。もうひとつの
Filter
を実行するウェブアプリケーションで の前に を実行するWebアプリケーションで、すでにリクエストボディを消費しています。getParameter()
,getParameterMap()
,getReader()
などです。リクエストボディは一度だけ解析することができます。ファイルアップロードフィルタが仕事をする前に、これらのメソッドの1つを呼び出すと、ファイルアップロードフィルタは空のリクエストボディを取得することになります。これを修正するためには、ファイルアップロードフィルタに
<filter-mapping>
を、ファイルアップロードフィルタの の前に にある他のフィルタのweb.xml
. もしリクエストがmultipart/form-data
リクエストでない場合、ファイルアップロードフィルタは何も起きなかったかのように処理を続けます。アノテーションを使用しているために自動的に追加されるフィルタ (例: PrettyFaces) を使用している場合は、web.xml で明示的に順序を追加する必要があるかもしれません。以下を参照してください。 WAR でアノテーションを使用してサーブレットフィルタの実行順序を定義する方法 -
PrimeFacesのファイルアップロードフィルタを使用している場合のみです。もうひとつの
Filter
を実行するウェブアプリケーションで の前に の前に実行され、PrimeFacesのファイルアップロードフィルタでRequestDispatcher#forward()
を呼び出します。通常、URL リライトフィルタのような プリティフェイス がこれを行います。これがトリガーとなってFORWARD
ディスパッチャを起動しますが、フィルタはデフォルトでREQUEST
ディスパッチャのみを listen します。これを修正するためには、PrimeFacesのファイルアップロードフィルタに の前に に置くか、PrimeFacesのファイルアップロードフィルタを再設定して
FORWARD
ディスパッチャもリッスンするようにPrimeFacesのファイルアップロードフィルタを再構成します。<filter-mapping> <filter-name>primeFacesFileUploadFilter</filter-name> <servlet-name>facesServlet</servlet-name> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping>
-
ネストされた
<h:form>
. これはHTMLでは違法であり、ブラウザの動作は不定です。多くの場合、ブラウザは送信時に期待されたデータを送信しません。を入れ子にしていないことを確認してください。<h:form>
. これは完全にフォームのenctype
. ただ、フォームをネストすることは一切ありません。
まだ問題がある場合は、まあ、HTTP トラフィックをデバッグしてください。ウェブブラウザの開発者ツールセット (Chrome/Firebug23+/IE9+ では F12 を押す) を開き、「Net/Network」セクションを確認します。HTTPの部分が問題なさそうなら、JSFのコードをデバッグしてください。ブレークポイントを
FileUploadRenderer#decode()
にブレークポイントを置き、そこから先に進みます。
アップロードしたファイルの保存
ようやく動作するようになったところで、次の質問はおそらく、「アップロードしたファイルをどこにどのように保存すればよいのですか?では、ここから先をご覧ください。 JSFでアップロードされたファイルを保存する方法 .
関連
-
[解決済み] javax.faces.application.ViewExpiredException: ビューを復元できませんでした
-
[解決済み] java.lang.ClassNotFoundException: javax.servlet.jsp.jstl.core.Config [duplicate].
-
[解決済み] javax.validation.ConstraintViolationException
-
[解決済み] actionとactionListenerの違い
-
[解決済み] commandButton/commandLink/ajax アクション/リスナーメソッドが呼び出されないか、入力値が設定/更新されない。
-
[解決済み】JSFリソースライブラリは何のためにあり、どのように使用すべきですか?
-
[解決済み】PrimeFacesのprocess/updateとJSFのf:ajax execute/renderの属性を理解する。
-
[解決済み] javax.el.PropertyNotFoundException の識別と解決。ターゲットに到達できない
-
[解決済み] divタグをレンダリングできるjsfコンポーネントは何ですか?
-
[解決済み] Backing Bean (@ManagedBean) か CDI Beans (@Named) か?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] javax.faces.application.ViewExpiredException: ビューを復元できませんでした
-
[解決済み] <f:facet>は何をするもので、どのような場合に使用するのですか?
-
[解決済み] JSF 2.2でターゲットが到達できない、識別子がヌルに解決される [重複] 。
-
[解決済み] java.lang.ClassNotFoundException: javax.servlet.jsp.jstl.core.Config [duplicate].
-
[解決済み] javax.validation.ConstraintViolationException
-
[解決済み] p:dashboardが終了してもソート順を維持する。
-
[解決済み] ビーンスコープを正しく選ぶには?
-
[解決済み】PrimeFacesのprocess/updateとJSFのf:ajax execute/renderの属性を理解する。
-
[解決済み] Java EE / JSF で j_security_check を使用してユーザー認証を行う。
-
[解決済み] <f:metadata>、<f:viewParam>、<f:viewAction>は何に使えるのでしょうか?