『PHP : 選択した画像の表示 / ファイルアップロード ver.2』 よりアップグレードします。 $.ajax と FormData オブジェクト を使用して画像をアップロードします。よって、HTML の FORM での送信は必要なくなります( HTML の入力チェックは必要時に使用する仕様なのでので FORM の記述は必要です ) ✅ control.php コントローラ ✅ model.php このバージョンでは使用しません ✅ view.php 画面定義 ✅ client.js FileReader オブジェクトを使用した、画像表示 ※ 複数選択が可能になっています ✅ upload.js $.ajax と FormData オブジェクト ✅ uplaod.php move_uploaded_file でアップロードされたファイルを保存するのが主な役割です。 ( 結果は JSON フォーマットで $.ajax に返します ) control.php $image_path は upload.php で使用するので、そちらへ移動しています。 ( $result_message ももう使用しません )
<?php // 不必要なエラー表示を行わない error_reporting( E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED ); // ブラウザのキャッシュに保存しない session_cache_limiter('nocache'); // セッションの開始 session_start(); // この ページの MIME( ページの種類 ) の設定 header( "Content-Type: text/html; charset=utf-8" ); // *********************************************** // 固有の処理 require_once("model.php"); // $image_path = "./myimages"; // $result_message = ""; // 画面 require_once("view.php"); // デバッグ //debug_print(); ?>
model.php ここは、もう使用しません( 標準化の為、model.php を削除する事はありません )
<?php // ******************************************** // このアプリケーション専用の処理 // ******************************************** // ******************************************************* // デバッグ // ******************************************************* function debug_print() { print "<pre>"; print_r( $_GET ); print_r( $_POST ); print_r( $_SESSION ); print_r( $_FILES ); print "</pre>"; } ?>
view.php 選択するファイルを画像限定にする為に、type="file" の INPUT 要素の属性に accept=".png,.jpg,.jpeg,.gif" を追加しています。また、アップロードを $.ajax で行うので FORM の enctype="multipart/form-data" は削除しています。
<!DOCTYPE html> <html> <head> <meta content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"> <meta charset="UTF-8"> <title>画像ファイルアップロード</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/css/bootstrap.css"> <script src="client.js?_=<?= time() ?>"></script> <script src="upload.js?_=<?= time() ?>"></script> </head> <body> <div id="head"> <div id="title"> <a href="./">画像をアップロード</a> </div> </div> <div id="content"> <form id="frm" method="POST"> <p> <input type="hidden" name="MAX_FILE_SIZE" value="1000000"> <input id="target" name="target" type="file" accept=".png,.jpg,.jpeg,.gif" class="ml-1 mt-3 btn btn-outline-primary"> </p> <p> <input type="submit" name="send" value="アップロード" class="ml-1 btn btn-outline-primary"> <a class="ml-4 btn btn-info btn-sm" href="<?= $_SERVER["PHP_SELF"] ?>">リロード</a> </p> <div id="image"></div> </form> </div> <div id="result"><?= $result_message ?></div> </body> </html>
client.js この部分は、ver.2 では選択は1つだけでしたが、今回は複数選択が可能になっています( クリアのタイミングが違うだけです )。 $("#image").html(""); による画像クリアをここで実行していません。画像のクリアは、upload.js の #.ajax の正常終了時のイベントの最後で行っています。
$(function(){ // INPUT type="file" のファイル選択後のイベント $("#target").on("change", function(){ // 選択されたファイルの情報 console.dir( this.files ); // ファイル参照用のクラス : FileReader var reader = new FileReader(); // 表示用にプロパティを追加 reader.name = this.files[0].name; reader.type = this.files[0].type; // 画像が読み込まれると実行されるイベント $(reader).on("load", function () { // FileReader の内容 console.dir( this ); if ( this.type.indexOf("image/") == 0 ) { $("<img>").appendTo("#image") .prop( {"src": this.result, "title": this.name + " : " + this.type } ) .css( {"width": "160px", "margin": "10px","border": "1px solid #c0c0c0" } ); } else { $("<img>").appendTo("#image") .prop( {"src": "./notimage.png", "title": this.name + " : " + this.type } ) .css( {"width": "160px", "margin": "10px","border": "1px solid #c0c0c0" } ); } }); if (this.files[0]) { // 画像を読み込み reader.readAsDataURL(this.files[0]); } }); });
upload.js $.ajax と FormData オブジェクトの処理です。但し、アップロードするデータは type="file" を持つ INPUT 要素で作成されるファイルオブジェクトでは無く、FileReader オブジェクトで作成された base64 の文字列を持つ画像を使用します。
$(function(){ // ************************************* // アップロード処理 // ************************************* $("#frm").submit( function(event){ // 本来の送信処理はキャンセルする event.preventDefault(); // アップロードする画像があるかどうかのチェック if ( $("#image").html() == "" ) { options.error("アップロードする画像ファイルを選択して下さい"); return; } if ( !confirm("アップロードを開始してもよろしいですか?") ) { return; } // 操作不可に設定 $("#content input").prop("disabled", true); // 結果の表示エリアを全てクリア $("#result").html( "" ); // ************************************** // ファイルのアップロード // ************************************** console.log("アップロード処理開始"); var formData = new FormData(); // 画像データサイズの制限 formData.append("MAX_FILE_SIZE", 10000000); var file_cnt = 0; $("#image img").each( function() { var base64 = $(this).prop("src"); var bin = atob(base64.split(',')[1]); var buffer = new Uint8Array(bin.length); for (var i = 0; i < bin.length; i++) { buffer[i] = bin.charCodeAt(i); } var blob = new Blob([buffer.buffer], {type: "application/octet-stream"}); file_cnt++; var file_name = (new Date()).getTime(); formData.append("image"+file_cnt, blob, file_name +"_"+file_cnt+".dat"); }); formData.append("FILE_COUNT", file_cnt ); $.ajax({ url: "./upload.php", type: "POST", data: formData, processData: false, // jQuery がデータを処理しないよう指定 contentType: false // jQuery が contentType を設定しないよう指定 }) .done(function( data, textStatus ){ console.log( "status:" + textStatus ); console.log( "data:" + JSON.stringify(data, null, " ") ); alert("アップロード処理が完了しました"); // アップロード結果の表示 $.each(data, function( idx, image ){ if ( image.error != 0 ) { $("#result").append("<span id=\"result" +idx+"\"></span><b style='color:red'>" + image.name+ " : " + image.result +"</b><br>"); } else { $("#result").append("<span id=\"result" +idx+"\"></span>" + image.name + " : " + image.result + "<br>"); } }); // 画像表示のクリア $("#image").html(""); }) .fail(function(jqXHR, textStatus, errorThrown ){ console.log( "status:" + textStatus ); console.log( "errorThrown:" + errorThrown ); }) .always(function() { // 操作不可を解除 $("#content input").prop("disabled", false); }) ; }); });
upload.php
サーバ側でファイルアップロードを担当する upload.php は、返すデータは JSON フォーマットであり、MIME は application/json です。これによって、$.ajax は直接 JSON オブジェクトを返す事になります。
<?php // キャラクタセット // ************************************* header( "Content-Type: application/json; charset=utf-8" ); // ************************************* // キャッシュ無効 // ************************************* session_cache_limiter('nocache'); session_start(); // ファイルを移動するフォルダ $image_path = "./myimages"; // フォルダが無ければ作成 if ( !is_dir( $image_path ) ) { mkdir( $image_path ); } $cnt = $_POST["FILE_COUNT"] + 0; for( $i = 0; $i < $cnt; $i++ ) { $image_target = "image".($i+1); if ( $_FILES[$image_target]["error"] == 0 ) { // ************************************* // 1) 画像フォーマットの取得 // ************************************* $type_string = image_type_to_mime_type( exif_imagetype( $_FILES[$image_target]['tmp_name'] ) ); // ************************************* // 2) オリジナルファイル名の取得 // ************************************* $file = explode(".", $_FILES[$image_target]['name']); // ************************************* // 3) 日本語ファイル名対応 // ************************************* $file_name = urlencode( $file[0] ); // ************************************* // 4) 保存ファイル名を作成 // a) 拡張子決定 // b) uniqid() でファイル目をユニーク // ************************************* $target = ""; if ( $type_string == "image/jpeg" ) { $target = uniqid() . "_{$file_name}.jpg"; } if ( $type_string == "image/gif" ) { $target = uniqid() . "_{$file_name}.gif"; } if ( $type_string == "image/png" ) { $target = uniqid() . "_{$file_name}.png"; } if ( $target == "" ) { $_FILES["image"]["result"][] = "アップロードできないフォーマットです"; } else { // ************************************* // アップロードファイルの保存 // ************************************* if ( @move_uploaded_file( $_FILES[$image_target]['tmp_name'], "{$image_path}/{$target}" ) ) { $_FILES[$image_target]["result"] = "アップロードに成功しました"; } else { // なんらかの環境エラー $_FILES[$image_target]["result"] = "アップロードに失敗しました"; } } } else { switch($_FILES[$image_target]["error"]){ case 1: $_FILES[$image_target]["result"] = "php.ini の upload_max_filesize ディレクティブの値を超えています"; break; case 2: $_FILES[$image_target]["result"] = "HTML フォームで指定された MAX_FILE_SIZE を超えています"; break; case 3: $_FILES[$image_target]["result"] = "一部のみしかアップロードされていません"; break; case 4: $_FILES[$image_target]["result"] = "アップロードされませんでした"; break; case 6: $_FILES[$image_target]["result"] = "テンポラリフォルダがありません"; break; case 7: $_FILES[$image_target]["result"] = "ディスクへの書き込みに失敗しました"; break; case 8: $_FILES[$image_target]["result"] = "PHP の拡張モジュールがファイルのアップロードを中止しました"; break; default: $_FILES[$image_target]["result"] = "不明なエラーです"; } } } print json_encode($_FILES) ?>
|
【PHP + WEBアプリの最新記事】
- PHP : 選択した画像の表示 / ファイルアップロード ver.2
- PHP : ファイルアップロード ver.1
- 超簡易掲示板 ( JSON ) : PHP / CSS でスマホ用レスポンシブ対応
- PHP : 曲線が必要ならば ImageMagick ( 但し使えるかどうかはサーバー次第 )
- GD で画像縮小。『1) 単純縮小、2) 幅にあわす 3) 高さにあわす 4) 任意の幅と高さ』をその他の処理も含めてクラスでまとめ( class GD )
- PHP : 超簡易ログ
- PHP + MySQL + IFRAME + Bootstrap : 問い合せ WEB アプリテンプレート
- Windows で Laravel を試す際、PHP の Windows バージョンが 5.6.30 なので、Laravel 5.2 をインストールします
- Laravel を試す為に Windows に Composer をインストール
- スマホ対応、サーバインデックス表示パッケージ( jQuery + Bootstrap(css) + mmenu + PHP )
- 超簡易掲示板 : 保存タイプは CSV
- PHP による『超簡易掲示板』 / アプリケーションからの POST 検証用
- PHP : 既存 GD 関連ライブラリで、背景をグラデーション(2)
- PHP : 既存 GD 関連ライブラリで、背景をグラデーション
- PHP : 入力値のデバッグ
- PHP : ImageMagick : 背景が透過する画像を作成
- PHP雛型(2会話DB更新処理) : MySQL、XMLHttpRequest、XML、JSON、Canvas
- PHP をテストする為の初心者用フォーム