JSF 2.2 で待ちに待ったFileUploadを試す

JSF 2.2 でやっと導入されたFileUploadを試してみました。


まずサーバ側のBackingBeanを作成します。

package sample;

import javax.inject.Named;
import javax.enterprise.context.RequestScoped;
import javax.servlet.http.Part;

@Named
@RequestScoped
public class UploadPage {

    private Part file;

    public Part getFile() {
        return file;
    }

    public void setFile(Part file) {
        this.file = file;
    }
}


JSFすごい。もはや処理すらありません。
fileのゲッターセッターを準備します。
ファイルはServlet3.0のファイルアップロードと同様にjavax.servlet.http.Partで受け取れます。


では送信するFecelets側の処理を書いてみましょう。

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html">
    <h:head>
        <title>Upload Test</title>
    </h:head>
    <h:body>
        <h:form enctype="multipart/form-data">
            <h:inputFile id="file" value="#{uploadPage.file}" /><br />
            <h:commandButton value="Upload" /><br />
            <h:outputText id="fileName" value="#{uploadPage.file == null ? '' : uploadPage.file.submittedFileName}" />
        </h:form>
    </h:body>
</html>


ファイルアップロードなのでもちろんformにenctype="multipart/form-data"を指定します。
あとはh:inputFileを配置するだけです。
ファイルが存在している場合はServlet3.1で追加されたsubmittedFileNameを呼び出してファイル名を表示しています。


最後にこのままだと日本語のファイル名が文字化けしてしまうのでglassfish-web.xmlにdefault-charsetでUTF-8を指定しておきます。NetBeansで自動生成したものに1行追加。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="">
  <class-loader delegate="true"/>
  <jsp-config>
    <property name="keepgenerated" value="true">
      <description>Keep a copy of the generated servlet class' java code.</description>
    </property>
  </jsp-config>
  <parameter-encoding default-charset="UTF-8" />
</glassfish-web-app>


では実行してみましょうファイルを添付して
f:id:den2sn:20130618233444p:plain


Uploadボタンを押すと
f:id:den2sn:20130618233500p:plain


無事ファイルがアップロードされてファイル名が表示されました。


では今度は処理をAjaxでのファイルアップロードに修正してみましょう。

<h:form enctype="multipart/form-data">
    <h:inputFile id="file" value="#{uploadPage.file}"></h:inputFile><br />
    <h:commandButton value="Upload">
        <f:ajax execute="@this" render="fileName" />
    </h:commandButton><br />
    <h:outputText id="fileName" value="#{uploadPage.file == null ? '' : uploadPage.file.submittedFileName}" />
</h:form>


では同じように実行してみましょうファイルを添付して
f:id:den2sn:20130618233444p:plain


Uploadボタンを押すと
f:id:den2sn:20130618234615p:plain


こちらも無事ファイルがアップロードされてファイル名が表示されました。AjaxによりoutputTextの部分しか更新されていないため入力部分のファイルのパスが消えていません。


実は現状AjaxのファイルアップロードはIEではもう一度実行しようとするとエラーになってしまいます。また、ChromeFirefox等の別のブラウザでは見えてはいけないiFrameが表示されて処理が途中で終了してしまいます。


GlassFishJSF実装のMojarraのJIRAに障害報告されているようなのでいずれ修正されると思います。