2009年8月23日日曜日

GAE/Jでアップロードした画像をデータストアに保存し、imgタグに出力する

upload.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>TEMPLATE</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
アップロードするファイル : <input type="file" name="imgfile" /><br>
<input type="submit" value="upload" />
</form>
<img src="/indication" alt="imgfile" />
</body>
</html>
UploadTest.javaにアップロードしたファイルをPostリクエストで送信
package org.test;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import org.test.DataStImg;
import org.test.PMF;

public class UploadTest extends HttpServlet {
private static final Logger log =
Logger.getLogger(UploadTest.class.getName());

public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {

PersistenceManager pm = PMF.get().getPersistenceManager();
final int size = 50000;
try{
ServletFileUpload upload = new ServletFileUpload();
upload.setSizeMax(size);//50KBの制限

FileItemIterator iterator = upload.getItemIterator(req);
while (iterator.hasNext()) {
FileItemStream item = iterator.next();
InputStream stream = item.openStream();

if(item.isFormField()){
log.warning("Got a form field: " + item.getFieldName());
} else {
log.warning("Got an uploaded file: " + item.getFieldName() +
", name = " + item.getName());
//ここからが大変だった。
ByteArrayOutputStream out = new ByteArrayOutputStream();
int len;
int i = 0;
byte[] buffer = new byte[1024];
while( (len = stream.read(buffer, 0, buffer.length)) != -1){
out.write(buffer, 0, len);

}
byte[] b = out.toByteArray();

//直す気力ないけどファイル名を取得して
//contentに入れればファイル名をキーに画像を呼び出せる。
String content = "content";
DataStImg ds = new DataStImg(content, b);
pm.makePersistent(ds);
pm.close();

resp.sendRedirect("/html/upload.html");
}
}
}
catch(Exception ex){
throw new ServletException(ex);
}
}
}
package org.test;

import java.util.Date;
import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

import com.google.appengine.api.datastore.Blob;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class DataStImg {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;

@Persistent
private Blob blob;

@Persistent
private String content;

public DataStImg(String content, byte[] buffer) {
blob = new Blob(buffer);
this.content = content;
System.out.println("In DataStImg");
}

public Long getId() {
return id;
}

public byte[] getImg() {
return blob.getBytes();
}

public String getContent() {
return content;
}

public void setImg(byte[] buffer) {

this.blob = blob;
}

public void setContent(String content) {
this.content = content;
}

}
Google app engineのFAQのところにあったコードを参考に作成。DataStImg.javaに画像データを保存し、再びupload.htmlにリダイレクト。imgタグsrc属性にservletを呼び出すためのURLを指定しておく。IndicationImg.javaにGETリクエストが送信される。
package org.test;

import java.util.List;
import java.io.*;
import javax.servlet.http.*;
import javax.servlet.*;
import javax.jdo.PersistenceManager;
import org.test.DataStImg;
import org.test.PMF;

public class IndicationImg extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException, ServletException {
resp.setContentType("image/png");
PersistenceManager pm = PMF.get().getPersistenceManager();

try {
String query = "select from " + DataStImg.class.getName();
List dss = (List) pm.newQuery(query).execute();
if (dss.isEmpty()) {
resp.sendRedirect("/html/upload.html");
} else {
for (DataStImg ds : dss) {
byte[] b = ds.getImg();
BufferedInputStream in = new BufferedInputStream(
new ByteArrayInputStream(b));

ServletOutputStream out = resp.getOutputStream();
int len;
while( (len = in.read(b, 0, b.length)) != -1) {
out.write(b, 0, len);
}

out.close();
in.close();
//まずは何番目の画像とか細かいこと考えず、
//とにかく最初に入れた画像を表示する
break;
}
}
}
catch(Exception e){
e.printStackTrace();
}
finally{
pm.close();
}
}
}
これで画像が表示される。

2009年8月22日土曜日

GAE/Jでのファイルアップロードについて

参考ページ(参考にしたソースコード)
参考ページ(使用できるフレームワークについての情報)
参考ページ(Apache Commons FileUploadについて)から1.2.1.tar.gzをダウンロードし、解凍。
できたフォルダから/commons-fileupload-1.2.1/lib/commons-fileupload-1.2.1.jarを/google/appengine/mydirectory/war/WEB-INF/lib/にコピー。
UploadTest.java
package org.test;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import java.util.logging.Logger;


public class UploadTest extends HttpServlet {
private static final Logger log =
Logger.getLogger(UploadTest.class.getName());

public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
try{
ServletFileUpload upload = new ServletFileUpload();
resp.setContentType("image/png");

FileItemIterator iterator = upload.getItemIterator(req);
while (iterator.hasNext()) {
FileItemStream item = iterator.next();
InputStream stream = item.openStream();

if(item.isFormField()){
log.warning("Got a form field: " + item.getFieldName());
} else {
log.warning("Got an uploaded file: " + item.getFieldName() +
", name = " + item.getName());
int len;
byte[] buffer = new byte[8192];
while((len = stream.read(buffer, 0, buffer.length)) != -1){
resp.getOutputStream().write(buffer, 0, len);
}
}
}
}
catch(Exception ex){
throw new ServletException(ex);
}
}
}
upload.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Upload</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
アップロードするファイル : <input type="file" name="imgfile" /><br>
<input type="submit" value="upload" />
</form>
</body>
</html>

2009年8月11日火曜日

chromiumをUSBブートのlxubuntuで使用してみて

Firefoxと比較して圧倒的に起動・動作共に早い。ただし、かなり不安定ではある。特にGoogleのサービスを使用しようとログインを試みると高頻度で落ちる。異常な終了をした場合、前のセッションを復元する機能があるため大きな問題になることはなかった。

少なくとも、USBブートをしている限りはFirefoxより圧倒的にパフォーマンスは良い。セキュリティに関する部分は間情報が少なく未知数で、情報が出揃ってくるまでは危ないサイトにはいかないようにすべき。

拡張機能は現段階では使用不能?

2009年8月10日月曜日

GAE/Jの間違いやすい?部分

参考ページ
参考ページ2
ここで詰まるのは少数派かもしれないがHttpURLConnectionクラスでリクエストを行うと日本語が文字化けを起こす。具体的にはPostRequest.java からのリクエストです→PostRequest.java???????????となってしまう。私は
package org.test;

import java.net.*;
import java.io.*;
import javax.servlet.http.*;

public class PostRequest extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
PrintWriter out = resp.getWriter();

URL url = new URL("http://localhost:8080/html/index.html");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("GET");

OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.close();

if(connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
BufferedReader reader = new BufferedReader(
new InputStreamReader(
connection.getInputStream()));
resp.setContentType("text/html;charset=UTF-8");
String line;
while( (line = reader.readLine()) != null ) {
out.println(line);
}
reader.close();
} else {
resp.setContentType("text/html;charset=UTF-8");
out.println("error");
}
}
}
のように書いていたが太字の部分をPrintWriter out = resp.getWriter();の上に書かなければならない。
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
//以下ほとんど同文


/html/index.html
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>PostRequest.javaからのリクエスト</title>

</head>
<body>
<p>PostRequest.java からのリクエストです</p>
</body>
</html>

2009年8月4日火曜日

Protocol Buffersについて勉強をする

参考ページ
JavaでProtocolBuffersを扱うにはソースコードからビルドする必要がある。基本的な手順は参考ページに書いてあるが細かいところでトラブルが起き、意外と手間がかかる。

作業ディレクトリについて
「ソースコードのルートディレクトリ/java」に移動と書いてあるがどれがそれなのか分かりにくい。ソースコードのルートディレクトリってどれ?ってことになる。
protobuf-*/javaディレクトリで作業を行う必要がある。

Java用ランタイムライブラリをビルドするときの注意点
OpenJDKではビルドエラーが発生してしまうため、環境変数JAVA_HOMEを適切なものにするために~/.bash_profileを

export JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.14/jre
export PAHT=$PATH:$JAVA_HOME
と編集し、
$ source ~/.bash_profile

とコマンドを実行

2009年8月3日月曜日

Protocol Buffersについて勉強

参考ページ
主にJavaについて参考にさせていただきました。あと、付属のサンプルも。

現時点で正直あんまり理解できていないがサンプルなどから推測するにあるデータがどのような構成になっているかを表現しているんじゃないかと思う。

//多分、違うのだろうから正解が分かったらちゃんと削除するようにしてください。

2009年8月1日土曜日

GAE for Javaをターミナルで開発する(AntによるJDOの初期設定について)

参考ページ
これによるとJDOを使用するのにantを用いる必要がある。
build.xmlファイルに
  <target name="datanucleusenhance" depends="compile"
description="Performs JDO enhancement on compiled data classes.">
<enhance_war war="war" />
</target>
を追加する必要があるがnew_project_templateからコピーし、作成したプロジェクトではこれだけではいけない。
$ ant datanucleusenhance
 
Unable to locate tools.jar. Expected to find it in /usr/lib/jvm/java-6-openjdk/lib/tools.jar
Buildfile: build.xml

compile:

datanucleusenhance:

BUILD FAILED
/home/something/gcode/appengine-java-sdk-1.2.0/demos/New_Project/build.xml:83: The following error occurred while executing this line:
/home/something/gcode/appengine-java-sdk-1.2.0/config/user/ant-macros.xml:94: /home/something/gcode/appengine-java-sdk-1.2.0/demos/New_Project/war/WEB-INF/classes not found.

Total time: 0 seconds
というエラーが出る
そのため
  <target name="datanucleusenhance" depends="compile"
description="Performs JDO enhancement on compiled data classes.">
<enhance_war war="${war.dir}" />
</target>
と太字の部分を変更する必要がある。