概要
以前の投稿PHPを用いたシンプルな画像ギャラリーにファイルのアップロード機能を追加してみた。
基本方針
ファイルのアップロードはajaxとFormDataオブジェクトを用いる。
フォームのactionで別ページに飛ぶのは避けたかったので色々調べた結果、ajaxを使用することで実現できる事が分かった。
実際の手順
1. 作成htmlの構成
HTML5で書いていきます。
※note1:jQuery.jsとlightbox用cssへのリンクが入ります。
※note2:type="file"のinputフォームを用います。
※note3:ギャラリーを表示する為の空のブロックです。
※note4:lightbox用JSは</body>の直前に配置します。
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="UTF-8">
<script src="http://code.jquery.com/jquery-latest.js" type="text/javascript"></script>
<link rel="stylesheet" href="./css/lightbox.css"> <!-- note1 -->
<title>画像アップロードギャラリー</title>
</head>
<body>
<section id="upform" class="upform">
<h1>アップロードする画像を選択してください</h1>
<form id="upload-form">
<input id="ufiles" type="file" name="ufiles[]" accept="image/*" multiple> <!-- note2 -->
</form>
<br>
<hr>
</section>
<section id="gallery" class="gallery">
<h1>アップロード画像一覧</h1>
<h3>クリックすると拡大表示されます</h3>
<div id="views" class="views"></div> <!-- note3 -->
</section>
<script>
<!-- ここにjQueryスクリプトを追加して行きます -->
</script>
<script type="text/javascript" src="./js/lightbox.js"></script> <!-- note4 -->
</body>
</html>
2. jQueryスクリプトの内容
※note5:function dmout()はjQuery.get()でシンプルなGETリクエストをサーバに送っています。サーバ側で"gallery.php"を実行し、結果を指定のHTML要素(ここではclass="views")へ出力します。ページがロードされた時とjQuery.ajax()が成功した時に呼ばれて実行されますが、これは他の良い方法を探した方が良いかも。
※note6:FormDataオブジェクトを作成しています。
newでインスタンスした後にappendメソッドで要素を追加しています。
複数ファイルを一度にアップロード出来るようinputフォームにmuliple属性を付加しているので、jQuery.each()を使用して全てのfile要素を順に追加しています。
※node7:jQuery.ajax()でAJAX通信を行います。FormDataを送信しhtmlを受け取ります。processDataとcontentTypeはfalseにする必要が有るとの事です。通信が正常に行われると.done(function())がコールバックされます。
$(function(){
// note5 ページロード時の呼び出し
domout("gallery.php", ".views");
// id="ufile"の変化でコールバック
$("#ufiles").change(function(){
// 選択ファイルの有無をチェック
if (!this.files.length) {
alert('ファイルが選択されていません');
return;
}
// note6 FormDataを用意
var fd = new FormData();
fd.append('action','upload-form');
$.each($("input[type='file']")[0].files, function(i, file) {
fd.append('ufiles['+i+']', file);
});
// note7 ajaxでFromDataを送信
$.ajax({
url: 'uploader_m.php',
type: 'POST',
processData: false,
contentType: false,
dataType: 'html',
data: fd
}).done(function(data, textStatus, jwXHR){
alert(data);
// note5 終了時の呼び出し
domout("gallery.php", ".views");
}).fail(function(jqXHR, textStatus, errorThrown){
alert('エラーが発生しました : ' + textStatus
+ "\nHTTP status : " + errorThrown);
});
});
});
// note5 DOMへhtmlを出力
function domout(_url, _html) {
$.get(_url, function(data) {
$(_html).html(data);
});
}
3. html全体
こんな感じです。
cssでサムネイルをちょこっと修飾しています。
<!DOCTYPE HTML>
<html lang="ja">
<head>
<meta charset="UTF-8">
<script src="http://code.jquery.com/jquery-latest.js" type="text/javascript"></script>
<!-- lightbox用CSS -->
<link rel="stylesheet" href="./css/lightbox.css">
<title>画像アップロードギャラリー</title>
<!-- サムネイルを見やすく -->
<style type="text/css"">
.image-link {
display: inline-block;
padding: 2px;
margin: 0 0.5rem 1rem 0.5rem;
background-color: #fff;
line-height: 0;
border-radius: 4px;
transition: background-color 0.5s ease-out; }
.image-link:hover {
background-color: #4ae;
transition: none; }
</style>
</head>
<body>
<section id="upform" class="upform">
<h1>アップロードする画像を選択してください</h1>
<form id="upload-form">
<input id="ufiles" type="file" name="ufiles[]" accept="image/*" multiple>
</form>
<br>
<hr>
</section>
<section id="gallery" class="gallery">
<h1>アップロード画像一覧</h1>
<h3>クリックすると拡大表示されます</h3>
<div id="views" class="views"></div>
</section>
<script>
$(function(){
//ページロード時の呼び出し
domout("gallery.php", ".views");
// id="ufile"の変化でコールバック
$("#ufiles").change(function(){
// 選択ファイルの有無をチェック
if (!this.files.length) {
alert('ファイルが選択されていません');
return;
}
// FormDataを用意
var fd = new FormData();
fd.append('action','upload-form');
$.each($("input[type='file']")[0].files, function(i, file) {
fd.append('ufiles['+i+']', file);
});
// ajaxでFromDataを送信
$.ajax({
url: 'uploader_m.php',
type: 'POST',
processData: false,
contentType: false,
dataType: 'html',
data: fd
}).done(function(data, textStatus, jwXHR){
alert(data);
//終了時の呼び出し
domout("gallery.php", ".views");
}).fail(function(jqXHR, textStatus, errorThrown){
alert('エラーが発生しました : ' + textStatus
+ "\nHTTP status : " + errorThrown);
});
});
});
// DOMへhtmlを出力
function domout(_url, _html) {
$.get(_url, function(data) {
$(_html).html(data);
});
}
</script>
<!-- lightbox用JS -->
<script type="text/javascript" src="./js/lightbox.js"></script>
</body>
</html>
4. ファイルアップロードするPHP
POSTされたファイル情報は$_FILESでPHPから参照できます。サーバ上では受信ファイルが"tmp_name"に保存されているので、アップロード先にmove_upload_file()で移動させています。アップロード先のディレクトリの書き込み権限に注意です。
<?php
define('FILE_PATH','./upload/'); //保存するパスを指定
if ( !empty($_FILES) ) {
for ( $i=0; $i<count($_FILES["ufiles"]["tmp_name"]); $i++ ) {
// アップロードされたファイルが有る事を確認
if (is_uploaded_file($_FILES["ufiles"]["tmp_name"][$i])) {
$saveFilename = FILE_PATH . $_FILES['ufiles']['name'][$i];
// ファイルの移動
if (move_uploaded_file($_FILES["ufiles"]["tmp_name"][$i], $saveFilename)) {
echo $_FILES["ufiles"]["name"][$i], "をアップロードしました\n";
} else {
echo $_FILES["ufiles"]["name"][$i], "アップロードエラー\n";
}
}
}
}
?>
5. ギャラリー用PHP
基本的にPHPを用いたシンプルな画像ギャラリーで使用したPHPと同じ内容ですが、ここではgetPictures()を呼んでおかないと実行されません。
<?php
$img_dir = './upload/';
function getPictures() {
global $img_dir;
$i = 0;
if ( $handle = opendir($img_dir) ) {
while ( ($file = readdir($handle)) !== false ) {
$path = $img_dir . $file;
if ( !is_dir($path) ) {
$split = explode('.', $file);
$name = $split[0];
$ext = $split[count($split) - 1];
if ( ($type = getPictureType($ext)) == '' ) {
continue;
}
echo '<a class="image-link" href="'.$path.'" data-lightbox="imgs" data-title="'.$name.'"><img class="image" src="'.$path.'" width="120" alt="'.$file.'">';
}
}
}
}
function getPictureType($ext) {
if ( preg_match('/jpg|jpeg/i', $ext) ) {
return 'jpg';
} else if ( preg_match('/png/i', $ext) ) {
return 'png';
} else if ( preg_match('/gif/i', $ext) ) {
return 'gif';
} else {
return '';
}
}
getPictures();
?>
結果
以下の環境で意図した動作を確認。
Edge 25.10586.0.0では上手く動作しなかったorz
サーバ情報
$ uname -a
Linux raspi-007 4.4.10-v7+ #885 SMP Fri May 13 15:44:27 BST 2016 armv7l GNU/Linux
$ php -version
PHP 5.6.20-0+deb8u1 (cli) (built: Apr 28 2016 00:01:26)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies
$ apachectl -v
Server version: Apache/2.4.10 (Raspbian)
Server built: Jan 23 2016 22:26:49
ブラウザ情報
FireFox 46.0.1
Chrome 51.0.2704.79 m
参考にさせて頂いたWEBサイト
http://chaika.hatenablog.com/entry/2014/04/12/001012
http://qiita.com/BRS_matsuoka/items/ba79a2f500a10ddc0923
http://stackoverflow.com/questions/12989442/uploading-multiple-files-using-formdata