広告

JavascriptとPHPでアップローダを作る

タグ:php web

画像ファイルなどを投稿するためのアップローダの作り方を紹介します。

これができたアップローダの例で、ドラッグ&ドロップで画像をアップロードすることができます。
ここにファイルをドロップ


    • ドラッグ&ドロップのインターフェースのためのHTMLファイル: upload.html
    • ドロップ時の動作を定義するためにjavascriptのjQueryというライブラリを使った dropfile.js
    • ファイルを保存するためのphpファイル: upload.php
    の3つを組み合わせて使います。
    参考にさせていただいたサイトは
    Javascriptの部分: http://qiita.com/tsunet111/items/0167704a65ebc04411f9
    HTML5の部分: http://wataame.sumomo.ne.jp/archives/3879
    です。

    まずドロップ用のボックスをhtmlで作ります。
    以下はサンプルコードです。
    	<!DOCTYPE HTML>
    	<html lang="ja">
    	  <head>
    	    <style type="text/css"><!--
    	      #dropzone {
    	        background-color: #ddd; min-height: 160px;
    	      }
    	      #dropzone.dropover {
    	        background-color: #ddd; color: #aaa;
    	      }
    	      #files:empty::before { color: #ccc; }
    	      #files img {
    	        max-height: 128px; max-width: 128px;
    	      }
    	    //--></style>
    	    <meta charset="UTF-8">
    	    <title>ファイルのアップロードのサンプル</title>
    	  </head>
    	  <body>
    
    	    <h3>ファイルのアップロードのサンプル</h3>
    
    	    <div id="dropzone" effectAllowed="move">ここにファイルをドロップ</div>
    	  	<ul id="files"></ul>
    	    <script src="./jquery-3.1.1.min.js"></script>
    	  	<script src="dropfile.js"></script>
    
    	  </body>
    	</html>
    

    <div id="dropzone" effectAllowed="move">ここにファイルをドロップ</div>
    という箇所がドロップ時の操作を定義したdropfile.jsと連絡してファイルを送信します。

    次にjavascriptファイル dropfile.jsにファイルを送信する機能を書きます。
    ここではファイルの送受信のためにjQueryというライブラリを使っています。
    http://jquery.com/download/からダウンロードできます。
    使うときはダウンロードできるjquery-3.3.1.min.jsかjquery-3.3.1.jsというファイルを
    upload.htmlと同じ階層に置けばOKです。
    	function postJump(files){
    	  //ファイルをupload.phpに送信
    	  var formdata = new FormData();
    	  $.each(files, function(i, file){
    			formdata.append('upfile' + i, file);
    		});
    	  // 送信
    	  $.ajax({
    	  	type: 'POST',
    	  	url : './upload.php',
    	  	data: formdata,
    	  	processData: false,	// jQueryがデータを処理しないように設定
    	  	contentType: false,	// jQueryがcontentTypeを設定しないように設定
    	  }).done(function(responseData, status, jqXHR)
    	  {
    	      console.log(responseData);
    	  }).fail(function(responseError, status, errorThrown)
    	  {
    	      console.log(responseError);
    	  });
    	}
    
    	(function() {
    		var elDrop = document.getElementById('dropzone');
    		var elFiles = document.getElementById('files');
    
    		elDrop.addEventListener('dragover', function(event) {
    				event.preventDefault();
    				event.dataTransfer.dropEffect = 'copy';
    		});
    
    		elDrop.addEventListener('drop', function(event) {
    				//ドロップ時にファイルをアップロード
    				event.preventDefault();
    				var files = event.dataTransfer.files;
    				showFiles(files);
    				postJump(files);
    		});
    
    		document.addEventListener('click', function(event) {
    			var elTarget = event.target;
    			if (elTarget.tagName === 'IMG') {
    				var src = elTarget.src;
    	      //クリックしたら別ウィンドウで画像を開く
    				var w = window.open('about:blank');
    				var d = w.document;
    				d.open();
    				d.write('<img src="' + src + '" />');
    				d.close();
    			}
    		});
    
    		function showFiles(files) {
    	    //アップロードされたファイルの情報を表示
    			for (var i=0, l=files.length; i<l; i++) {
    					var file = files[i];
    					var elFile = buildElFile(file);
    					elFiles.appendChild(elFile);
    			}
    		}
    
    		function buildElFile(file) {
    				var elFile = document.createElement('li');
    				var text = file.name + ' (' + file.type + ',' + file.size + 'bytes)';
    				elFile.appendChild(document.createTextNode(text));
    				if (file.type.indexOf('image/') === 0) {
    					var elImage = document.createElement('img');
    					elImage.src = "";
    					elFile.appendChild(elImage);
    					attachImage(file, elImage);
    				}
    				return elFile;
    		}
    
    		function attachImage(file, elImage) {
    			var reader = new FileReader();
    			reader.onload = function(event) {
    				var src = event.target.result;
    				elImage.src = src;
    				elImage.setAttribute('title', file.name);
    			};
    			reader.readAsDataURL(file);
    		}
    	})();
    
    この中で大事な部分はまず32行目の
    elDrop.addEventListener('drop', function(event) { ... }
    の部分で、ここでボックスにドロップされた時の動作(エベントリスナ)を定義しています。
    実際にファイルをアップロードするのはpostJump関数で、これがファイルをまとめたのちに
    ファイルを保存してくれるupload.phpへPOSTリクエストで送信しています。


    最後にdropfile.jsのPOSTリクエストを受け取るupload.phpを用意します。
    これは$_FILESの要素を一つずつ保存するもので、必要なエラーチェックなどもします。
    <?php
    //参考 http://wataame.sumomo.ne.jp/archives/3879
    header("Content-Type: text/html; charset=UTF-8");
    define('FILE_PATH','./images/'); //保存するパスを指定
    
    if ( !empty($_FILES) ) {
      for ( $i=0; $i<count($_FILES); $i++ ) {
    		echo $_FILES;
    		$upfile_i = 'upfile' . $i; //i個目のファイル
    		if ( is_uploaded_file($_FILES[$upfile_i]['tmp_name']) ) {
    			$name = $_FILES[$upfile_i]['name'];
    			$tempFile = $_FILES[$upfile_i]['tmp_name'];
    			print_r($_FILES[$upfile_i]);
    
    			// Validate the file type
    			$fileTypes = array('jpg','jpeg','gif','png');   // File extensions
    			$fileParts = pathinfo($_FILES[$upfile_i]['name']);
    
    			// ファイル名がアルファベットのみかをチェック
    			if ( preg_match("/^([a-zA-Z0-9\.\-\_])+$/ui", $name) == "0" ) {
    			    // アルファベット以外を含む場合はファイル名を日時とする
    			    $saveFileName = date("Ymd_His", time());
    			}
    			else {
    			  echo "ファイル: $name\n";
    			  if ( preg_match("/\.jpg$/ui", $name) == true ) {
    			      $ret = explode('.jpg', $name);
    			  }
    				elseif ( preg_match("/\.gif$/ui", $name) == true ) {
    			      $ret = explode('.gif', $name);
    			  }
    				elseif ( preg_match("/\.png$/ui", $name) == true ) {
    			      $ret = explode('.png', $name);
    			  }
    			  $saveFileName = $ret[0]; // 拡張子を除いたそのまま
    			}
    
    			// マイクロ秒をファイル名に付加
    			$saveFileName = FILE_PATH . '[' . (microtime()*1000000) . ']' . $saveFileName;
    			if ( in_array($fileParts['extension'], $fileTypes) )
    			{
    				if ( move_uploaded_file($_FILES[$upfile_i]["tmp_name"],
    					$saveFileName . '.' . $fileParts['extension']) )
    				{
    					//chmod($saveFileName . '.' . $fileParts['extension'], 0777);
    					echo $_FILES[$upfile_i]["name"] . "をアップロードしました。\n";
    				}
    				else {
    					echo "アップロードエラー";
    				}
    			}
    			else {
    			  echo "アップロードの対象は画像ファイル(.jpg/.gif/.png)のみです。<br>\n";
    			  $filename = $_FILES[$upfile_i]['name'];
    			  echo "ファイル: $filename";
    			}
    		}
    		else {
    			echo "アップロードエラー: ファイルがアップロードされていません。\n";
    		}
    	}
    }
    else {
      echo "アップロードエラー: FILESが空です。";
    }
    ?>
    

    以上の3ファイルを置いたディレクトリにさらにimages/というサブディレクトリをつくっておけば、
    そこに画像ファイルが保存されていきます。