解説コードを読んでみよう
このサンプルでわかること
- プラグインを使うと、プレビュー機能を1行で付けられること
multipleを付けて、1つの入力欄で複数の画像を選ぶ方法- 複数選択したとき、PHP の
$_FILESがどうなるか
前のサンプルでは FileReader を使ってプレビューを自分で作りました。同じことを、配布されている jQuery プラグイン「Upload Thumbs」に任せてみます。
使っているファイル
- index.php2つの入力フォームと、プラグインを動かす JavaScript
- ../js/jquery.upload_thumbs.jsUpload Thumbs プラグイン本体
- data.php送信されたテキストとファイルの情報を表示する PHP
1. プラグインを読み込む
jQuery 本体を読み込んだあと(サイト共通のヘッダーで読み込み済み)に、プラグインのファイルを読み込みます。
<!-- このサンプルで使うプラグイン(jQuery 本体のあとに読み込む) -->
<script src="../js/jquery.upload_thumbs.js"></script>
2. 入力フォーム:1枚用と複数枚用
<h3>画像を1枚選ぶ</h3>
<form action="data.php" method="post" enctype="multipart/form-data">
<table class="thumb-form">
<tr><th>テキスト</th><th>画像(1枚)</th></tr>
<tr>
<td><input type="text" name="text[]"></td>
<td><label><input type="file" name="img[]" accept="image/*"></label></td>
</tr>
</table>
<input type="submit" class="btn btn-default" name="send" value="送信">
</form>
<hr>
<h3>画像を複数枚選ぶ</h3>
<form action="data.php" method="post" enctype="multipart/form-data">
<table class="thumb-form">
<tr><th>テキスト</th><th>画像(複数可)</th></tr>
<tr>
<td><input type="text" name="text[]"></td>
<td><label><input type="file" name="img[]" accept="image/*" multiple></label></td>
</tr>
</table>
<input type="submit" class="btn btn-default" name="send" value="送信">
</form>
2つのフォームの違いは、36行目の multiple だけです。これを付けると、ファイルを選ぶ画面で Ctrl キー(Mac は ⌘ キー)を押しながら複数の画像を選べるようになります。
入力欄を <label> で囲んでいるのは、プラグインの機能で「表示されたサムネイルをクリックすると、画像を選び直せる」ようにするためです。
3. プラグインを実行する
<script>
$(function() {
// ページ内のすべての画像入力欄に、プレビュー機能を付ける
$('form input:file').uploadThumbs({
position : 0, // 0 = 入力欄の「前」にサムネイルを入れる
imgbreak : true // サムネイルのあとで改行する
});
});
</script>
$('form input:file') で、ページ内のすべての画像入力欄(type="file")を選び、.uploadThumbs({ ... }) でプラグインを実行しています。
| オプション | 意味 |
|---|---|
position | サムネイルを入れる場所。0 は入力欄の前、1 は後ろ |
imgbreak | true にするとサムネイルの後ろに改行(<br>)を入れる |
プラグインの中では、前のサンプルと同じく FileReader の readAsDataURL() で画像を読み込んでいます。複数枚に対応したり、選び直したときに古いサムネイルを消したりといった細かい処理まで済ませてくれるのが、プラグインを使う利点です。
4. 複数枚選んだときの $_FILES
複数枚用のフォームで3枚選んで送ると、$_POST['text'] は1つなのに、$_FILES['img']['name'] には3つのファイル名が入ります。1つの入力欄で選んだファイルが、全部 img[] の配列に並ぶためです。
[img] => Array
(
[name] => Array ( [0] => a.jpg [1] => b.jpg [2] => c.png )
[type] => Array ( [0] => image/jpeg [1] => image/jpeg [2] => image/png )
...
)
そのため data.php では、テキストと画像を別々の表にして、画像は $_FILES['img']['name'] の数だけ表示しています。
<h3>画像($_FILES['img'])</h3>
<?php $names = (array)($files['name'] ?? []); ?>
<p>受け取ったファイルは <strong><?= count($names) ?> 個</strong>です。</p>
<table class="table table-striped">
<tr><th>i</th><th>ファイル名 (name)</th><th>種類 (type)</th><th>サイズ (size)</th><th>error</th></tr>
<?php foreach ($names as $i => $name): ?>
<tr>
<td><?= h($i) ?></td>
<td><?= h($name) ?></td>
<td><?= h($files['type'][$i] ?? '') ?></td>
<td><?= h(number_format((int)($files['size'][$i] ?? 0))) ?> バイト</td>
<td><?= h($files['error'][$i] ?? '') ?></td>
</tr>
<?php endforeach; ?>
</table>
このプラグインは2015年ごろに作られたもので、古い Internet Explorer 向けの処理も含まれています。今のブラウザでは問題なく動きますが、新しく作るなら前のサンプルのように FileReader で自分で書く方法も覚えておくと安心です。
書き直したポイント
- 以前のページはプラグインのファイルを読み込んでいなかったため、プレビューが表示されていませんでした。
<script src="../js/jquery.upload_thumbs.js">を追加しています。 - 受け取る PHP は、何も送られていないときに PHP 8 で警告が出ないよう、
?? []で初期値を決めています。
position を 1 に変えると、サムネイルが入力欄の後ろに表示されます。数字を変えて違いを確かめてみましょう。