CMSでは画像をアップロードする場面が少なくないと思いますが、通常のフォームでは投稿した後にならないと実際のアップロード後のイメージを見ることができません。
そこで、今回要望があって作ることになったんですがファイルを選択した時点で画像のプレビューを表示し、気に入ったものが選択できた時点で他のテキストなどのテータと共に投稿するというインターフェイスを作ってみました。
実際の作り方は以下のとおり。
プレビューの仕組み
まず、この仕組みがどうなっているのかを説明しますと、ファイルを選択したイベントでいったんアップロードを行ってしまい画像ファイルを作業ディレクトリに保存します。
そして、その後でJavaScriptでプレビュー領域にimgタグを出力して表示を行います。
ポイントは、アップロードの際に隠しiframeをtargetに指定してすぐにその値を元に戻すという部分の処理です。
それには、以下のようなJavaScriptを使います(要prototype.js)。
function autoexec()
{
Event.observe($('image'), 'change', changeImgPath, false);
}
function changeImgPath(e)
{
var org_action = $('myform').action;
$('myform').action = 'preview.php';
$('myform').target = 'preview_iframe';
$('myform').submit();
$('myform').action = org_action;
$('myform').target = null;
}
Event.observe(window, "load", autoexec);
外部JSにしたかったので上記のようにしていますが、changeBody関数をonchangeに関連付けてもいけます。
これによって、例えば以下のようなHTMLで画像選択時にiframeに対するPOSTを発生させることができるようになります。
<form enctype="multipart/form-data"
method="post" id="myform" action="post.php">
<input type="file" name="image" id="image" />
<div id="preview">
プレビュー:
<div id="preview_img">
</div>
</div>
<input type="submit" value="送信" />
</form>
<iframe name="preview_iframe" id="preview_iframe" width="0"
height="0" scrolling="no" frameborder="0"></iframe>
PHP側では、単に通常のアップロード処理やファイルの形式チェックなどを行い、正しいデータならば画像ファイルを作業ディレクトリに移動させるだけです。
アップロード後の出力データは、以下のような感じになります。
<script language="JavaScript" type="text/javascript">
window.parent.document.getElementById("preview_img").
innerHTML='<?php print image_tag("/".
sfConfig::get("sf_upload_dir_name")."/preview/".$filename) ?>';
</script>
php部分はsymfonyの関数を使っていますが単にimgタグを出力しているだけです。
これによって、
- 画像ファイル選択
- 隠しiframeへアップロード
- preview_imgへimgタグを書き出すJavaScriptを隠しiframeに出力
- 画像がプレビュー表示される
という動きが実現できます。
上記を実装したサンプルコードをダウンロードできるようにしました。
昔は、単純なJavaScriptでonchangeでimgタグのsrcにfileのvalueを入れて簡易プレビューを作ったこともあるのですが、IEではいけるのですがFirefoxなどではセキュリティ上の理由で表示できなくなった(当然か・・)ので、上記のようなものを作りました。
Gmailの添付ファイルの処理も似たようなことをやっているのではないかと想像してみたり。。

参考になりました。
とても助かりました。
ありがとう御座いました。