昨今、ファイルをアップロードするならば、JavsScript を駆使して UI を作成し、 $.ajax で送信したほうが簡潔になりますが、ベタな FORM の記述のみで送信してそれなりのレスポンスを得ようという処理です。 デモページ 画像をクリックするとデモページへ移動します当然ですが、デモページで実際のアップロードはできません。しかし、結果を表示するにチェックを入れて送信すると、上の画像のように実際と同じ状態で情報をシミュレートします。 UI の構築を気楽に工夫できるように、twitter-bootstrap の 4.1.3 を組み込んでいます IFRAME は本来非表示で、ここに JavaScript で右上のメッセージ(toastr.js)を表示するようにしていますが、デバッグ用としても使えるようにしており、その場合は PHP 側の $_FILES の中身が見れるようになっています。 type="file" の name 属性は target で固定して php 側で使用しています。送信データの制限 データの制限はサーバに対する無意味なアクセスを遮断するアプローチと、アプリから見たデータの制限という二つのアプローチがあります。前者がもっとも重要で、それがなければ php.ini の upload_max_filesize 内であれば結果的にそのサイズまでは送信を許してしまいます。 ※ upload_max_filesize を超えると $_FILES そのものが空になるようです。 後者は、FORM 内の name="MAX_FILE_SIZE" の値で指定できますが、完全な対策ではありません。 そこで、対象ページのあるディレクトリの .htaccess 内に 『LimitRequestBody 102400』のように制限値を設定し、さらに『ErrorDocument 413』 を設定してそのページの中でエラー処理の対応をしています ▼ 413.html
<!DOCTYPE html> <html lang="ja"> <meta charset="utf-8"> <style> * { font-size: 32px; } </style> <script> try { parent.$("iframe").show(); parent.toastr.info( "ファイル のアップロードに失敗しました"); parent.toastr.info( "エラー内容 : Request Entity Too Large" ); } catch (e) {} </script> </head> <body> JavaScript の処理用に IFRAME を定義している場合で、 413 Request Entity Too Large が発生した場合にこのページが IFRAME 内に表示されます。 </body> </html>
file_upload_html.php $debug 変数で、実際のアップロードの可否を切り替えています。if ( !$_FILES ) { の部分は、upload_max_filesize を超えてしまった状態の対処ですが、ここでは LimitRequestBody 102400 を設定しているので発生する事はありません。
<?php session_cache_limiter('nocache'); session_start(); header( "Content-Type: text/html; charset=utf-8" ); // ************************************* // 変数初期値 // ************************************* $debug = 0; $upload_dir = "./upload"; if ( !$_FILES ) { // php.ini の upload_max_filesize を超えて、 // Apache に制限が無いと $_FILE が空になる $_FILES['target']['error'] = 5; // ユーザエラーメッセージ } // ************************************* // アップロード処理 // フィールド名 : target で固定 // ************************************* if ( $_SERVER['REQUEST_METHOD'] == "POST" ) { // 公開状態では実行しない if ( $debug == 1 ) { $upload = realpath ( $upload_dir ); $upload .= ( DIRECTORY_SEPARATOR . $_FILES['target']['name'] ); if ( move_uploaded_file( $_FILES['target']['tmp_name'], $upload ) ) { $_POST['result'] = "アップロードに成功しました"; } else { if ( !$_FILES ) { $_FILES['target']['error'] = 5; // ユーザエラーメッセージ } $_POST['result'] = "アップロードに失敗しました"; } } else { if ( $_FILES['target']['error'] == 0 ) { $_POST['result'] = "アップロードに成功しました"; } else { $_POST['result'] = "アップロードに失敗しました"; } } } else { $_POST['result'] = "POST メソッドを使用して下さい"; } $_POST['files'] = $_FILES; // ************************************* // この JSON 文字列を HTML 内の json // オブジェクト定義として埋め込みます // ************************************* $json = json_encode($_POST, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE ); // ************************************* // 画面定義 // ************************************* ?> <!DOCTYPE html> <html lang="ja"> <style> /* calc 用 */ html,body { height: 100%; } body { margin: 0; } * { font-size: 16px; font-family: "ヒラギノ角ゴPro W6","Hiragino Kaku Gothic Pro W6","メイリオ",Meiryo,"MS Pゴシック",Verdana,Arial,Helvetica,sans-serif; } </style> <script> var message = <?php require("error.json.php") ?> var json = <?= $json ?>; if ( json.files.target.error == 0 ) { parent.toastr.info(json.files.target.name + " がアップロードされました"); parent.toastr.info("ファイルサイズ : " + json.files.target.size); } else { parent.toastr.info(json.files.target.name + " のアップロードに失敗しました"); parent.toastr.info("エラー内容 : " + message.error[json.files.target.error]); } <?php if( $_POST["disp_result"] == "1" ) { ?> parent.$("iframe[name='upload']") .css("border", "1px solid #c0c0c0") .show(); <?php } else { ?> parent.$("iframe[name='upload']").hide(); <?php } ?> </script> </head> <body> <?php if( $_POST["disp_result"] == "1" ) { ?> <textarea style='width:calc(100% - 6px);height:calc(100% - 14px);'><?= $json ?></textarea> <?php } ?> </body> </html>
error.json.php は、PHP のエラーメッセージです。ここでは部品として埋め込んでいますが、$.ajax バージョンでも使用(error.json.php?type=json)しています。 error.json.php
<?php if ( $_GET["type"] == "json" ) { session_cache_limiter('nocache'); session_start(); header( "Content-Type: application/json; charset=utf-8" ); } ?> { "error": [ "0 - 正常終了", "1 - アップロードされたファイルは、php.ini の upload_max_filesize ディレクティブの値を超えています", "2 - アップロードされたファイルは、HTML フォームで指定された MAX_FILE_SIZE を超えています", "3 - アップロードされたファイルは一部のみしかアップロードされていません", "4 - ファイルはアップロードされませんでした", "5 - 『アップロードに失敗しました』", "6 - テンポラリフォルダがありません。PHP 5.0.3 で導入されました", "7 - ディスクへの書き込みに失敗しました。PHP 5.1.0 で導入されました", "8 - PHP の拡張モジュールがファイルのアップロードを中止しました" ] }
upload.html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta content="width=device-width initial-scale=1.0 minimum-scale=1.0 maximum-scale=1.0 user-scalable=no" name="viewport"> <title>HTML の FORM のみでファイルを一つアップロードする</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <link id="link" rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/base/jquery-ui.css"> <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.css"> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.qrcode/1.0/jquery.qrcode.min.js"></script> <!-- 共通の表示 --> <link rel="stylesheet" href="common.css"> <!-- CSS の指定 --> <style> #top { height: 420px; } iframe { display: block; margin-left: auto; margin-right: auto; width: calc( 100% - 3px ); height: calc( 100% - 420px - 2px ); } /* PC 用の表示 */ @media screen and ( min-width:480px ) { #content { margin: 16px; } } /* スマホ用の表示 */ @media screen and ( max-width:479px ) { #content { margin: 0px; } body { width: 100%!important; margin: 0px; } .unit { width: 100%; } .btn { margin-top: 7px; } } </style> <script> // 簡易的なスマホチェックを jQuery のプロパティとして登録 jQuery.isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase())); if ( $.isMobile ) { // スマホの場合は表示画面下の中央 toastr.options.positionClass = "toast-bottom-center"; } $(function(){ // このページ自身の QRコードの表示 $('#qrcode') .css({ "margin" : "2px" }) .qrcode({width: 160,height: 160,text: location.href }); }); </script> </head> <body> <div id="top"> <div id="head"> <div id="title"> <a href="./">One File アップロード</a> </div> </div> <div id="content"> <form target="upload" enctype="multipart/form-data" action="../../php_upload/file_upload_html.php" method="POST"> <input type="hidden" name="MAX_FILE_SIZE" value="40000"> <input name="target" type="file" class="btn btn-info"> <input type="submit" value="ファイルを送信" class="btn btn-success ml-2"> <p> <label for="disp_result">結果を表示する</label> <input id="disp_result" type="checkbox" name="disp_result" value="1" class="mt-5" checked> </p> </form> <div id="qrcode"></div> </div> </div> <iframe src="about:blank" name="upload" style="display:none;border:0px solid #c0c0c0;width:100%;"></iframe> </body> </html>
common.css
@charset "UTF-8"; /* calc 用 */ html,body { height: 100%; } body { margin: 0; } /* 共通の表示 */ * { font-size: 16px; font-family: "ヒラギノ角ゴPro W6","Hiragino Kaku Gothic Pro W6","メイリオ",Meiryo,"MS Pゴシック",Verdana,Arial,Helvetica,sans-serif; } #head { background-color: #404040; padding: 10px 0 10px 25px; } #head * { color: #ffffff; }
HTML 側のダウンロード PHP 側のダウンロード
|
【PHP + 通信の最新記事】
- fake sendmail for windows を使って、PHP でごく普通に( mb_send_mail で )メール送信
- PHP の cURL でファイルアップロード
- PHP : WEB でもコマンドラインでも HTTP でファイルをダウンロードする 『fget.php』
- PHP : cURL : Google Photo API の albums.list メソッドを使用して アルバム一覧データを取得する
- PHP + cURL で Google Photo API の アクセストークンを取得する
- PHP : cURL で FTP + SSL ダウンロード
- PHP の imap 関数で( Windows ローカル )、Yahoo メールのメールをさくらインターネットのメールへコピーする
- PHP の imap 関数( Windows のローカル )で、さくらインターネットのメールボックスの情報を取得する
- PHP : IMAP 関数 でまずメールのヘッダ部分を整理してログに出力する / ※ JSON 出力を追加
- Pear の Net_POP3 で、SSL(995) を使って簡単にメール受信
- PHP をコマンドプロンプトから実行して、WEB 上のデータを取得するいくつかの方法
- FormData を使用して $.ajax で送信すると、ファイルのアップロードとメール送信(ファイル添付)を一度に行えます
- ファイルのアップロードからそれを添付してメールを送るテンプレート(スケルトン)
- PHP : mb_send_mail を使用した自家用メール送信 API
- PHP で Windows標準のオブジェクト(CDO.Message)とGMail を使ってメール送信
- PHP : http 経由でファイルのサイズを取得する file_size 関数と ファイルサイズを付加した get_imagesize 関数
- 連想配列のキー部分がプロパティと一致したらセットする( メール送信用クラス )
- PHP : リモートのファイルサイズを取得する
- ローカルの PHP を使ってコマンドプロンプトより簡単にバイナリファイルをアップロードする
- PHP の cURL で ftp サーバーにファイルをアップロードする(SSLなし)