gmailで添付ファイルが自動でアップロードされるしくみ

gmailでメールを書くとき、添付するファイルを選んでからしばらくすると、いつの間にか添付ファイルがアップロードされています。

添付するファイルを選ぶと、はじめファイル名が表示されていたのが
しばらくすると
自動的にアップロードされて、名前とファイルサイズが表示されています!

実は、あまり名前も聞かなくなった Google Page Creator がリリースされたときにいちばんびっくりしたのはページの右下にこのgmailの自動アップロードとよく似たしくみがあったことでした。で、さっそく解析してマネしてみたことがあります。今回はgmailでその仕組みを見てみます。

ちなみにその Google Page Creator には、ログインすると右下にこんな
ファイルをアップロードするのに使う部分があります。 gmailの場合、メールが自動保存されるタイミングでアップロードされているかんじでしたが、こっちのはBrowseボタンを押してファイルを選ぶとすぐにファイルがアップロードされます。
そしてgmailの添付ファイルのときと同様に、ファイル名とファイルサイズが表示されます。

処理の流れ

処理は極めて単純で、<input type="file"> のchangeイベントを監視して、変化があったときにself.form.submit() で自分自身が属するformをsubmitしています。 このときformタグの属性にtargetが設定されているのがミソです。gmailの場合formタグは
<form id="compose_form" class="cf cn" onsubmit="return false" 
enctype="multipart/form-data" method="post" target="hst" accept-charset="utf-8" action="">
になっています。targetに設定されているhstはiframeになっていました。ただ、インラインのスタイルシートで left: -10000px; が設定されているので画面には表示されないようになっています。余談ですが、自分でこれと同じ仕組みをマネして作るときは、動くようになるまで画面の中にirameを表示されるようにしてエラーを見たりできる状態にしておいて、完成したときに画面の外に飛ばすスタイルをつけるとデバッグが楽になります。
<iframe id="hst" scrolling="auto" frameborder="0" 
onload="try{if(top.js.init)top.js._IF_OnLoaded('hst')}catch(e){}" 
style="width: 100%; height: 100%; position: absolute; top: 0pt; left: -10000px;" 
src="https://mail.google.com/mail/?view=page&name=hist1" name="hst">
スクリプトによってiframeをターゲットにしてsubmitされると、iframeの中のコンテンツが書き変わります。 iframeに表示されるコンテンツはjavascriptを実行するためのHTMLです。(一部セッションキーっぽいところは書き換えてあります)
<html><head><meta content="text/html; charset=UTF-8" http-equiv="content-type"></head>
<script>D=(top.js&&top.js.init)?function(d){top.js.P(window,d)}:function(){};
if(window==top){top.location="/mail/?ik\u003d02ad21601d&cmid\u003d1&newatt\u003d1&rematt\u003d0&autosave\u003d1&fs\u003d1";}
</script>
<script><!--
D(["v","lynnnnnnnn5r","66eeeeeeeeee2","37","1","1x4nxxxxxxxxxxxx"]
);
D(["ds",[["inbox",0]
,["drafts",122]
,["spam",6490]
]
]
);
D(["sr","1",1,"Your message has been saved.","112c3167d00000000",1,[["0.1","kbd.jpg","image/jpeg",828,-1,"f_f0000000"]
]
,"9:46 pm",0,0,1,"23",,0,[]
,[]
]
);
D(["ds",[["inbox",0]
,["drafts",122]
,["spam",6490]
]
]
);

//--></script>
<script>var loaded=true;D(['e',5,1180097217948]);</script>

ここから先は読んでいませんが、おそらくDという名前の関数がgmailの本体側で定義されていて、その関数の中で表示を書き換えているのでしょう。

やっていることは XMLHttpRequest + JSONP とおなじで、ただファイルをアップロードするときにtargetを設定しなければページ遷移が起きてしまうので、ブラウザ上で見えない位置に配置したiframeをtargetにしてsubmitしているわけです。

へんな値を入れてみる

ちなみにこの方法、ローカルのファイルを調べたりする特別な何かがあるわけでもなく、単純にスクリプトでsubmitボタンを押させているだけなので、ちょっとへんなことをするとへんになります。ためしに存在しないファイル名を入力して
アップロードされるのを待つと
エラー処理がいい加減なようで、0バイトのファイルが添付されちゃいます。

画像ファイルのアップロードをAjaxぽくできる

で、ウェブメールのクライアントとか、FTPクライアントもどきを作るならともかく、ふつうのウェブアプリケーションでこんなの何に使うのって話になりますが、ユーザのプロフィール編集画面などで使うのは有効ではないでしょうか。 ほかのフォーム要素、テキストエリアやチェックボックスの場合changeイベントをハンドルして自動的にデータをサーバに送って同期を取るのは一般的ですが、プロフィールの画像だけは最後にsubmitを押さないと反映されない、みたいなインターフェイスにするしかありませんでした。 が、この方法を使えば <input type="file" /> で画像ファイルを選択した瞬間にアップロード、サムネイルを生成してユーザのプロフィール画像を即反映させる、というUIを作ることができます。

ファイルのアップロードだけボタンを押さないといけないのがインターフェイスとして美しくないと感じていたならば、この方法でAjaxっぽいUIを実現してみてはいかがでしょう。

追記 5/28

はてなブックマークで irohiroki さんにコメントいただいて Rubyist - yamazのRails日記 - Ajaxっぽく画面遷移なしでファイルアップロードしたい! に書かれているとおり Ruby on Rails には遷移なしでアップロードするためのpluginがあるそうです。RoRすごい!


tags

  • javascript
  • 「gmailで添付ファイルが自動でアップロードされるしくみ」のはてなブックマーク数
  • 「gmailで添付ファイルが自動でアップロードされるしくみ」deliciousブックマーク数
  • 「gmailで添付ファイルが自動でアップロードされるしくみ」をはてなブックマークに追加
  • save "gmailで添付ファイルが自動でアップロードされるしくみ" to del.icio.us
  • 「gmailで添付ファイルが自動でアップロードされるしくみ」をリアルタイムブログ検索
  • permalink
  • ファイルの先頭8バイトだけで画像のフォーマットを調べる
  • LWP::UserAgentでBASIC認証つきでリクエストする

comments

TypeKey Enabled
スタイル用のHTMLタグが使えます。
*required
111
2007.05.27 08:22

!ぽおおおおおお!

trackbacks

トラックバック元エントリにこのエントリへのリンクがない場合はトラックバックを受け付けません。

http://labs.gmo.jp/mt/mt-tb.cgi/127
©2010 Kentaro Kumagai, GMO Internet Labs., GMO Internet, inc.
bits and bytes
2007 .05. 25 22:13

tagcloud

  • API1
  • C/C++2
  • E4X1
  • FUSE2
  • Firefox18
  • HTML4
  • IE1
  • MySQL1
  • OSX4
  • Opera2
  • PHP4
  • XML1
  • XPCOM4
  • XPath3
  • apache2
  • binary2
  • book1
  • data11
  • debug4
  • design1
  • experiments3
  • extension10
  • google gears1
  • google maps API1
  • greasemonkey3
  • httpd5
  • javascript17
  • linux1
  • logging2
  • mobile3
  • perl4
  • tips4
  • tool11
  • vim2
  • visualization2
  • widget1
  • wii1
  • windows7
  • サービス6
  • 和訳1

Archives

  • 2008.02 (6)
  • 2008.01 (3)
  • 2007.12 (4)
  • 2007.11 (5)
  • 2007.10 (4)
  • 2007.09 (4)
  • 2007.08 (4)
  • 2007.07 (8)
  • 2007.06 (7)
  • 2007.05 (4)
  • 2007.04 (5)
  • 2007.03 (6)
  • 2007.02 (4)
  • 2007.01 (6)

about

  • bits and bytesのXML
  • 「bits and bytes」のCreative Commons
  • Powered by Movable Type
  • イベントと地図 - モグ
  • Use ecto to blog!
  • bits and bytesのはてなブックマーク数
  • bits and bytesをMy Yahoo!に追加
  • Subscribe with Bloglines