Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
6
Help us understand the problem. What is going on with this article?
@Quramy

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として登録してくれるため、特に設定ファイル等の記載は不要.

参考リンク

6
Help us understand the problem. What is going on with this article?
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
Quramy
Front-end web developer. TypeScript, Angular and Vim, weapon of choice.

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
6
Help us understand the problem. What is going on with this article?