SyntaxHighlighter

2011年8月16日火曜日

GAE, Slim3, Scenic3 環境下でAjaxなBlobstore利用

検証コード書いてちゃんと動作したので備忘録的な感じで。
後日丁寧に書く予定。とりあえず箇条書き

前提
・jQuery.upload利用
・コントローラ側は「アップロードURL返す」「Blobstoreアップロードからの戻り直後」「戻り直後からリダイレクトされJSON生成」の3段階用意


1,アップロードボタン押す
2,UploadUrlリクエスト、Jsonで取得しそのままアップロード
3,戻りURLをコントローラを指定しておいて、そこに戻す。そのタイミングではRedirectでなければ戻せない約束事なので一旦別のコントローラにリダイレクト(画像URLを一緒に渡す)
4,別のコントローラは画像URLをJSON化してクライアントに戻す
5,クライアントはAJAXな動きでBLOBSTOREを利用することができる


リクエスト用HTML&JavaScript
<!--
BlobStore直接アップロード検証コード
 -->

<script type = "text/javascript" src="/jquery.upload-1.0.2.js"></script>
<input type="file" name="newprofileimage" id="newprofileimage" />
<input type="button" name="entry" value="登録" onclick='javascript:submitUpload("newprofileimage");' />
<br />
<br />

<script type="text/javascript">
function submitUpload(targetid)
{
 var jsonUrl = "/image/getdirectupdurl";
 var uploadurl = "";

 $.getJSON(jsonUrl, function(urldata) {

  if(urldata)
  {
   uploadurl = urldata.url;

   $('#' + targetid ).upload(
    uploadurl,
	function(data)
	{
	 alert('File uploaded[' + data[0].imageurl + ']');
	 $('#imagearea').html('<img src="' + data[0].imageurl +  '" />');
	},
	'json'
   );
   }
  });
}
</script>

<div id="imagearea">アップロード後の画像が表示される場所</div>

サーバサイドコード
/**
 * BlobStoreへの直接アップロード用URLを取得する.
 * JSON形式にて返す
 * @return
 */
@ActionPath("getdirectupdurl")
public Navigation getDirectUploadUrl()
{
 Navigation nav = null;

 String returnUrl = "/image/dupdcomplete";
 String uploadUrl = service.createUploadUrl(returnUrl); //BlobstoreServiceのcreateUploadUrlを呼び出している

 Map<String,String> jsonData = new HashMap<String,String>();
 jsonData.put("url", uploadUrl);

 try
 {
  nav = this.responseJson(jsonData);
 }
 catch (IOException e)
 {
  e.printStackTrace();
  nav = this.redirect("errorurl");
 }

 return nav;
}


/**
 * Blobstoreに直接アップロードした後、リダイレクトされる場所
 * @param blobUrl
 * @return
 */
@ActionPath("dupdcomplete")
public Navigation directUploadComplete()
{
 Navigation nav = null;

 BlobKey blobKey = service.getBlobKey(request, "newprofileimage");

 nav = this.redirect( "/image/dupdrd?bloburl=" + service.getServingUrl(blobKey));

 return nav;
}

/**
 * Blobstoreに直接アップロードした後リダイレクトされたものをさらにリダイレクトされる場所.
 * @param blobUrl
 * @return
 */
@ActionPath("dupdrd")
public Navigation forDirectUploadRedirect(
  @RequestParam("bloburl") String blobUrl
)
{
 Navigation nav = null;

 if(blobUrl != null && blobUrl.isEmpty() == false )
 {
  List<Map<String,String>> jsonDataList = new ArrayList<Map<String,String>>();

  Map<String,String> jsonData = new HashMap<String,String>();
  jsonData.put("imageurl", blobUrl);
  jsonDataList.add(jsonData);

  try
  {
   nav = this.responseForImageJson(jsonDataList);//この前のエントリの内容
  }
  catch (IOException e)
  {
   e.printStackTrace();
  }
 }

 return nav;
}

2011年8月15日月曜日

GAE/J Slim3でScenic環境下でjQuery uploadを利用&Jsonで戻りデータ取得

結論からいいますと、やっつけデス。。。
コードはかなり美しさにかけて、めっちゃ遅いんちゃう!?くらいの勢いですがとりあえず動きます。

ポイント。

  • jQuery.uploadはjsonでリクエストした際、iframeを利用してシームレスなアップロードを実現するためJsonデータが戻ってくる際のContentTypeが「text/html」でないと<pre>タグがついてしまってうまく処理できない
  • Scenic側でNavigationオブジェクトを渡す際、responseJsonで渡すと強制的に「text/JavaScript」になってしまう

そらそうや、ってお話です。JSONですし。
responseJsonした後にContentTypeを強制的に変えれればなんとかなりそうだったんですが、全く変えれず。。。setContentTypeは意味をなさない。
responseJsonしたあとにキャッシュ的なんと_out〜とかいう変数に1が入ってるのがポイントなんじゃろか?

response( String ) でJson文字列を自分で作って渡してやればいいんじゃないか!?と思いましたが、強制的に「text/Plain」になりました。

結果、responseDirect( byte[], String(=ContentType) ) を使うことにしました。
以下、ざっくり手順を。


  1. まず、StringBufferなどでJSON文字列を作成します。
  2. 次にStringBuffer.toString.toCharArrayでchar[]配列を取り出します
  3. char[]配列の長さでbyte[]配列を作成
  4. ひたすらchar[]配列をループして1つずつbyte[]配列にコピー!!!(これなんかええのんないかなー?)
  5. 最後にresponseDirectに渡してやって完了。

あ、ContentTypeは「"text/html; charset=UTF-8"」みたいな感じで。

とりあえず動きました。ええ、とりあえず。。。

まぁここの部分はファイルアップロードで1個画像を扱うだけなんで、もういいかな?とも思ったり。
まぁ後で時間できたときに見直しですねぇ。今は動けばいいや(涙

2011年8月9日火曜日

GAE/J デプロイにて 409 conflict が出た場合の対処

本日のGAEの障害?(19時〜のやつ)のタイミングでデプロイしてまして、その時は結局デプロイできなかったので数時間経ってから再度デプロイを行いました。
すると、失敗した時の何かが残っていたのか
「Unable to update app:〜ほにゃらら〜409 Conflict」
と表示されました。
これの対処について備忘録もかねて記述しておきます

メッセージには
「Another transaction by user〜」
と出ており
「That user can undo the transaction with "appcfg rollback".」
てなメッセージが出ていました。

調べてみると、コマンドラインから上記コマンドを実行してやればよいようです


machine:~ hoge$ cd /Applications/eclipse/plugins/com.google.appengine.eclipse.sdkbundle_1.5.2.r36v201107221751/appengine-java-sdk-1.5.2/bin/
machine:bin hoge$ ls -al
total 32
drwxr-xr-x   6 hoge  hoge  204  8  2 07:27 .
drwxr-xr-x  14 hoge  hoge  476  8  2 07:27 ..
-rw-r--r--   1 hoge  hoge  276  7 22 15:02 appcfg.cmd
-rw-r--r--   1 hoge  hoge  582  7 22 15:02 appcfg.sh
-rw-r--r--   1 hoge  hoge  368  7 22 15:02 dev_appserver.cmd
-rw-r--r--   1 hoge  hoge  670  7 22 15:02 dev_appserver.sh

なんかそれっぽいのがいました。実行権限を付与して、実行してみる
machine:bin hoge$ ./appcfg.sh rollback /myproject/war/
Reading application configuration data...
2011/08/09 22:26:06 com.google.apphosting.utils.config.AppEngineWebXmlReader readAppEngineWebXml
####: Successfully processed /myproject/war/WEB-INF/appengine-web.xml
2011/08/09 22:26:06 com.google.apphosting.utils.config.AbstractConfigXmlReader readConfigXml
####: Successfully processed /myproject/war/WEB-INF/web.xml
2011/08/09 22:26:06 com.google.apphosting.utils.config.AbstractConfigXmlReader readConfigXml
####: Successfully processed /myproject/war/WEB-INF/cron.xml
2011/08/09 22:26:06 com.google.apphosting.utils.config.AbstractConfigXmlReader readConfigXml
####: Successfully processed /myproject/war/WEB-INF/queue.xml
2011/08/09 22:26:06 com.google.apphosting.utils.config.IndexesXmlReader readConfigXml
####: Successfully processed /myproject/war/WEB-INF/appengine-generated/datastore-indexes-auto.xml
Beginning server interaction for myproject...
0%  on backend null.
Email: *****@gmail.com
Password for *****@gmail.com: *****
Success.
Cleaning up temporary files...
machine:bin hoge$ 

EmailとPasswordはデプロイする権限のあるユーザを入力しました
この後、通常通りにデプロイすることでデプロイが完了しました

2011年8月7日日曜日

INFOBARの飛散防止フィルムを剥がしてみた

INFOBAR買ったんです。

んで、しばらく裸で使ってたんですが、なんか滑りが悪いというか。。。

んでシャープ機で飛散防止フィルム剥がしたら滑りが良くなった的な書き込みをみたのでレッツチャレンジ。
iPhoneも他のスマートフォンも裸運用なので気にしない!




端っこをコンパスの針でガリガリやって、無理やりチョっぴり剥がせるようにして、あとは指でジワジワと。
多少しっかり貼りついているフィルムって感じで、剥がした後はすこし粘着感。

ウェットティッシュで拭いて、トレシーでガッツリ拭いてやるととってもスッキリしました

剥がした後の操作感は・・・ああ、気持ちいい。
これでやっとiPhoneの裸ガラスと同じ滑り感。




ただ、裏のプロセスが重い時は滑りがよくても操作がついてきません

心なしか発色もフィルム無しだけにキレイになったような?
つか、海外モデルは飛散防止フィルムなんて貼ってないよね。心配性な日本人の姿勢が製品に現れてるんかなぁ。。。




保障がなくなるかも?ってことなので、自己責任で!