LoginSignup
1
1

More than 5 years have passed since last update.

アップロード付きシンプル画像ギャラリー

Posted at

概要

以前の投稿PHPを用いたシンプルな画像ギャラリーにファイルのアップロード機能を追加してみた。

基本方針

ファイルのアップロードはajaxとFormDataオブジェクトを用いる。
フォームのactionで別ページに飛ぶのは避けたかったので色々調べた結果、ajaxを使用することで実現できる事が分かった。

実際の手順

1. 作成htmlの構成

HTML5で書いていきます。
※note1:jQuery.jsとlightbox用cssへのリンクが入ります。
※note2:type="file"のinputフォームを用います。
※note3:ギャラリーを表示する為の空のブロックです。
※note4:lightbox用JSは</body>の直前に配置します。

sceleton.html
<!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())がコールバックされます。

jquery.script
        $(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でサムネイルをちょこっと修飾しています。

index.html
<!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()で移動させています。アップロード先のディレクトリの書き込み権限に注意です。

upload_m.php
<?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()を呼んでおかないと実行されません。

gallery.php
<?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

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1