6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Posted at

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

背景

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

  • 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
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?