ファイルのアップロード
Google App Engineでは、サーバ上でファイルを扱うことができません。各種データはオンメモリで取り回し、保存が必要な場合にはDatastore Java APIを利用して、Google App Engineの擬似データベースに取り込む必要があります。Datastore Java APIについては、今後の記事でご紹介したいと思います。
Javaで書かれたウェブサービスのファイルアップロードライブラリと言えば、通常Apache CommonsのFileUploadを指すと思いますが、このライブラリはディスク上でデータを取り扱うので、アップロードされたデータをオンメモリで処理するためのクラスを追加します。
まず、Apache Commonsの「FileUpload 1.2.1」と依存ライブラリの「IO 1.4」のバイナリをダウンロードします。それぞれ展開後のディレクトリから「commons-fileupload-1.2.1.jar」と「commons-io-1.4.jar」を「war/WEB-INF/lib」にコピーします。

「commons-fileupload-1.2.1.jar」はコンパイルに必要なので、ビルドパスに追加します。準備ができたら、[com.daisukeyamashita.test.images]パッケージに以下の2つのクラスを追加して下さい。
package com.daisukeyamashita.test.images;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemHeaders;
import org.apache.commons.fileupload.FileItemHeadersSupport;
import org.apache.commons.fileupload.ParameterParser;
public class MemoryFileItem implements FileItem, FileItemHeadersSupport {
private static final long serialVersionUID = -2531086814081783645L;
public static final String DEFAULT_CHARSET = "ISO-8859-1";
private String fieldName;
private String contentType;
private boolean isFormField;
private String fileName;
private long size = -1;
private byte[] cachedContent = null;
private FileItemHeaders headers = null;
public MemoryFileItem(String fieldName, String contentType, boolean isFormField, String fileName) {
this.fieldName = fieldName;
this.contentType = contentType;
this.isFormField = isFormField;
this.fileName = fileName;
}
public void delete() {
cachedContent = null;
baos = null;
}
public byte[] get() {
if (isInMemory()) {
if (cachedContent == null) {
cachedContent = baos.toByteArray();
}
return cachedContent;
}
return new byte[0];
}
public String getContentType() {
return contentType;
}
public String getFieldName() {
return fieldName;
}
public InputStream getInputStream() throws IOException {
if (cachedContent == null) {
cachedContent = baos.toByteArray();
}
return new ByteArrayInputStream(cachedContent);
}
public String getName() {
return fileName;
}
private ByteArrayOutputStream baos = null;
public OutputStream getOutputStream() throws IOException {
if (baos == null) {
baos = new ByteArrayOutputStream();
}
return baos;
}
public long getSize() {
if (size >= 0) {
return size;
} else if (cachedContent != null) {
return cachedContent.length;
} else if (baos != null) {
return baos.toByteArray().length;
}
return 0;
}
public String getString() {
byte[] rawdata = get();
String charset = getCharSet();
if (charset == null) {
charset = DEFAULT_CHARSET;
}
try {
return new String(rawdata, charset);
} catch (UnsupportedEncodingException e) {
return new String(rawdata);
}
}
@SuppressWarnings("unchecked")
public String getCharSet() {
ParameterParser parser = new ParameterParser();
parser.setLowerCaseNames(true);
// Parameter parser can handle null input
Map params = parser.parse(getContentType(), ';');
return (String) params.get("charset");
}
public String getString(String encoding) throws UnsupportedEncodingException {
return new String(get(), encoding);
}
public boolean isFormField() {
return isFormField;
}
public boolean isInMemory() {
return true;
}
public void setFieldName(String name) {
this.fieldName = name;
}
public void setFormField(boolean state) {
this.isFormField = state;
}
public void write(File file) throws Exception {
// no process;
}
public FileItemHeaders getHeaders() {
return headers;
}
public void setHeaders(FileItemHeaders headers) {
this.headers = headers;
}
}
package com.daisukeyamashita.test.images;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
public class MemoryFileItemFactory implements FileItemFactory {
public MemoryFileItemFactory() {
}
public FileItem createItem(String fieldName, String contentType, boolean isFormField,
String fileName) {
MemoryFileItem result = new MemoryFileItem(fieldName, contentType, isFormField, fileName);
return result;
}
}
