Posted at

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

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


参考リンク