これまでのあらすじ
Apache Wicketで作っているナニカで JavaScript 経由の FileUpload 処理が実装したい場面に遭遇しました。
Wicket で Rest といえば、wicketstuff-restannotations。
Qiitaにも記事を上げている先人がいますし、リンク先のドキュメントを見ればまあだいたい使い方はわかるのですが、FileUpload のサンプルは見当たらない。
というわけで、とりあえず力技っぽいけどこれで動いたぜというメモを残すことにしたのです。
バージョンとか
- Wicket 8.1.0
- wicketstuff-restannotations 8.1.0
- Commons FileUpload バンザイ
- wicketstuff-restannotationsの使い方とかの説明はナシ
実装とか
呼び元。てきとう。
いまさらJQueryと思わなくもないけれど、そこはほらWicketだから。
<!DOCTYPE html>
<html>
<body>
<input type="file" id="file-select" style="display:none">
<button id="file-button">ファイル選択</button>
<script>
$('#file-button').click(function(e) {
$("#file-select").click();
});
$("#file-select").change(function(e) {
var file = e.target.files;
if(file.length > 0) {
var form = new FormData();
form.append('image', file[0]);
var settings = {
"async": false,
"crossDomain": false,
"url": "fileUpload",
"method": "POST",
"dataType": "text",
"processData": false,
"contentType": false,
"data": form
}
$.ajax(settings).done(function (response) {
if(result.success) {
alert(response);
}
});
}
});
</script>
</body>
</html>
RestResource。
ここで FileUpload の FileItem が取得できるのが当面の目標かと。
JSONでのレスポンスとか普通はすると思うのだけれど、そこらへんは省略。
あと関係ないけれど、AbstractRestResourceが総称型な理由がよくわからん。
package yamane.rest;
import org.apache.commons.fileupload.FileItem;
import org.wicketstuff.rest.annotations.MethodMapping;
import org.wicketstuff.rest.annotations.parameters.RequestBody;
import org.wicketstuff.rest.contenthandling.mimetypes.RestMimeTypes;
import org.wicketstuff.rest.resource.AbstractRestResource;
import org.wicketstuff.rest.utils.http.HttpMethod;
public class FileUploadResource extends AbstractRestResource<FileUploadSerialDeserial> {
public FileUploadResource() {
super(new FileUploadSerialDeserial());
}
@MethodMapping(
value = "/fileUpload",
httpMethod = HttpMethod.POST,
produces = RestMimeTypes.TEXT_PLAIN
)
public String saveImage(@RequestBody FileItem item) {
// FileItem さえ取得できれば勝ちだよね!
return item.getFieldName();
}
}
キモの部分、IWebSerialDeserial。
まあHttpServletRequestをとってきてFileUploadでパースするだけなんですが。
該当処理以外はだいぶ適当。該当処理もまあまあ適当。
関係ないけれど、SerialDeserialって名前はどうなんだろう。
package yamane.rest;
import java.io.File;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.protocol.http.servlet.ServletWebRequest;
import org.apache.wicket.request.http.WebRequest;
import org.apache.wicket.request.http.WebResponse;
import org.wicketstuff.rest.contenthandling.IWebSerialDeserial;
public class FileUploadSerialDeserial implements IWebSerialDeserial {
DiskFileItemFactory factory = new DiskFileItemFactory();
FileUploadSerialDeserial() {
ServletContext context = WebApplication.get().getServletContext();
File repository = (File) context.getAttribute("javax.servlet.context.tempdir");
factory.setRepository(repository);
}
@Override
public void objectToResponse(Object str, WebResponse response, String mimeType) throws WicketRuntimeException {
ServletResponse sResponse = (ServletResponse) response.getContainerResponse();
sResponse.setCharacterEncoding("UTF-8");
response.write((CharSequence) str);
}
@Override
@SuppressWarnings("unchecked")
public <T> T requestToObject(
WebRequest wRequest,
Class<T> argClass,
String mimeType) throws WicketRuntimeException {
try {
ServletWebRequest sRequest = (ServletWebRequest) wRequest;
HttpServletRequest request = sRequest.getContainerRequest();
ServletFileUpload fileUpload = new ServletFileUpload(factory);
List<FileItem> items = fileUpload.parseRequest(request);
return !items.isEmpty() ? (T) items.get(0) : null;
} catch (FileUploadException e) {
throw new WicketRuntimeException(e);
}
}
@Override
public boolean isMimeTypeSupported(String mimeType) {
return true;
}
}
今回はここまで
というわけで、JavaScript経由のファイルが無事に取得できました。
雑な記事ですが、まあメモってことで許してください。