Help us understand the problem. What is going on with this article?

JBossのRESTEasyにおけるMultipart Requestの文字化け対策

More than 5 years have passed since last update.

仕事で若干困ったのと、文字化け系の現象なのだが、同内容の対応についての日本語ページがまったく引っ掛からなかったので、メモしておく.

背景

やろうとしていたことは、↓.

  • multipart/form-dataでJAX-RS(JBoss EAP 6.2, RestEASY)にファイルをUpload.
  • フォームデータには日本語を許可.

コードのイメージは下記な感じだ.

FileResource.java
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.jboss.resteasy.annotations.providers.multipart.MultipartForm;

@Path("/file")
public class FileResource {

    @POST
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response create(@MultipartForm UploadData uploadData){

        String fileName = uploadData.getFileName(); // ★ こいつが文字化!
        // 色々処理...
        return Response.ok().build();
    }
}
UploadData.java
public class UploadData implements Serializable{
    private String fileName;
    private byte[] fileBody;
    public String getFileName() {
        return fileName;
    }
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
    public byte[] getFileBody() {
        return fileBody;
    }
    public void setFileBody(byte[] fileBody) {
        this.fileBody = fileBody;
    }


}   

RESTEasyの拡張アノテーション@MultipartFormでデータの取得をしようとするも、日本語を含む項目が悉く文字化けする.

原因

仕方なく、multipart関連のProvider実装(org.jboss.resteasy:resteasy-multipart-provider:2.3.6-final)のソースを読んでみたところ、org.jboss.resteasy.plugins.providers.multipart.InputPart のJavadocに下記が書いてあった.

    /**
     * If there is a content-type header without a charset parameter, charset=US-ASCII
     * is assumed.
     * <p>
    * This can be overwritten by setting a different String value in
    * {@link org.jboss.resteasy.spi.HttpRequest#setAttribute(String, Object)}
    * with this ("resteasy.provider.multipart.inputpart.defaultCharset")
    * String as key. It should be done in a
    * {@link org.jboss.resteasy.spi.interception.PreProcessInterceptor}.
    * </p>
     */
    static final String DEFAULT_CHARSET_PROPERTY = "resteasy.provider.multipart.inputpart.defaultCharset";

要は、「multipartの各partについて、content-type=○○; charset=... のようなヘッダが無い場合, ProviderはUS-ASCIIで文字コード変換するよ」という内容だ.

対応方法

JavaDocにも書いてある通り、org.jboss.resteasy.spi.HttpRequest#setAttribute"resteasy.provider.multipart.inputpart.defaultCharset"をセットする方法でやってみたところ、無事解決(なお、後からこのキー名でググってみたら、JavaDocだけでなく、RESTEasy本家のドキュメントにも記載がありました...).

ContentTypeSetterPreProcessorInterceptor.java
import org.jboss.resteasy.plugins.providers.multipart.InputPart;

@Provider
@ServerInterceptor
public class ContentTypeSetterPreProcessorInterceptor implements
        PreProcessInterceptor {

    public ServerResponse preProcess(HttpRequest request,
            ResourceMethod method) throws Failure, WebApplicationException {
        request.setAttribute(InputPart.DEFAULT_CHARSET_PROPERTY, "UTF-8");
        return null;
    }

}

PreProcessInterceptorhttp://docs.jboss.org/resteasy/docs/2.3.6.Final/userguide/html_single/index.html#PreProcessInterceptors にもある通り、RESTEasyのリクエスト時に HttpRequestへの拡張ポイントとして利用できる. @Providerが付与されていれば、勝手にJBossがInterceptorとして登録してくれるため、特に設定ファイル等の記載は不要.

参考リンク

Quramy
Front-end web developer. TypeScript, Angular and Vim, weapon of choice.
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした