page_adsence

2011年9月7日水曜日

画面遷移なしで画像のアップロードをするときの罠

Ajaxを使って画面遷移なしで画像をアップロードするってことになったらしく、
調べてみたら別にできないことではないし、やってる人はいっぱいいるみたいでした。
で、早速やってみたら以外にサクッといけた。

Javascript単体でファイルのアップロードはできないので、サーバ側にデータをPOSTする必要がある。
だけど普通にPOSTすると画面遷移が発生してしまう。
それを回避するためにiframeを使用する。
普通にformでpostする際には(1)のように記述するが、
画面遷移なしでやる場合には(2)のように記述する必要がある。

(1)通常
<form action="test" method="post">
form elements…
</form>

(2)
<iframe name="iframeName"></iframe>
<form action="tset" method="post" target="iframeName">
form elements…
</form>

このようにすると、POSTされたデータ自体はiframeに飛んでいき、
iframe内で画面遷移が発生するが、現在ページを表示している方には影響がない。
また、iframe自体を画面外に飛ばしておくことで、ユーザーには遷移が行われていることを見られずに
画像をアップロードすることが可能になる。

但し何点が注意点がある。
1つはformのPOST先であるiframeをdisplay:noneにするような形で対応すると、
Safariでtargetに指定したiframeではなく、新しいウィンドウに対してPOSTされてしまうので注意が必要である。

2つ目はサーバ側からクライアントに対してデータを返す際のContent-Typeだ。
通常サーバ側でjsonを返す場合のContent-Typeは「application/json」だが、
「application/json」で返すと謎のnoscriptタグにメッセージが付加されて返ってきてしまい、
jsonオブジェクトのパースに失敗するが、「text/javascript」にしてみたらいけた。
しかし、jquery.uploadのライブラリを使ってアップしようとした場合には「text/html」で返すように指定してねって記述があるので、実は「text/html」が一番いいのかも知れない。
今回は色々と切羽詰まっていて、複数ブラウザで確認していないのでなんとも言えませんが、
ライブラリが使っているContent-Typeが安全そう。

まぁ自分で実装する機会があればぜひやってみよう。