こちらからアクセスできます 左は通常のログイン前の表示で、右はログイン後の表示です。ログイン後は、フォルダから下の全てのファイルを zip 書庫でダウンロード可能になります。また、下部のパスが、ドキュメントルートからの表示になります。( logout と入力するとログアウトされます ) インストールは、好きな場所に保存して、このインデックスを表示したい最上位フォルダに .htaccess を置いてDirectoryIndex /toolbox/data2/index/files.phpのように、保存したパスを DirectoryIndex で指定するだけです実行するカレントフォルダは保存した場所となりますが、呼び出されるのは各フォルダから呼び出されるので、$_SERVER['REQUEST_URI'] となり、その場所を使ってフォルダ・ファィルの一覧を表示しています。files.php ログインパスワードは、files.php に以下のように指定します
<?php session_cache_limiter('nocache'); session_start(); $GLOBALS['pass'] = 'パスワード'; require_once("view_main.php"); ?>
session_cache_limiter('nocache') は、キャッシュを使用しないヘッダをブラウザに返すようにする処理です。 セッションを使ったログインの処理は、new FormData() で作成した FormData オブジェクトを使用して、jQuery の $.ajax で呼び出しています。 戻りの JSON オブジェクトは、json_encode($_POST) によって、view_main.php が返しています。そして、ログインが成功したら、location.reload(true) でページをリロードしてセッションの処理を有効化します。 view_main.php
<?php // REQUEST_URI は呼び出し元のパス $GLOBALS['path'] = explode("?", $_SERVER['REQUEST_URI']); require_once("download.php"); // ************************************* // フォルダ内を全て zip でダウンロード // ************************************* if ( $_GET['download'] != "" ) { if ( $_SESSION['login'] == 'yes' ) { $result = download(); } else { header( "Content-Type: text/html; charset=utf-8" ); print "ログインされていません"; } exit(); } // ************************************* // ログイン処理 // 1) ダウンロード可能 // 2)パスを DOCUMENT_ROOT で表示 // ************************************* if ( $_GET['login'] == "yes" ) { header( "Content-Type: application/json; charset=utf-8" ); if ( $_POST['pass'] == $GLOBALS['pass'] && $GLOBALS['pass'] != "" ) { $_SESSION['login'] = 'yes'; $_POST['login'] = 'yes'; } else { // ログアウト if ( $_POST['pass'] == 'logout' ) { // セッションをクリア $_SESSION = array(); $_POST['login'] = 'logout'; } else { $_POST['login'] = 'no'; } } // ブラウザへ JSON 文字列で結果を返す print json_encode($_POST); exit(); } header( "Content-Type: text/html; charset=utf-8" ); // ************************************* // 表示コントロール // ************************************* $GLOBALS['title'] = "インデックス"; $GLOBALS['comment'] = $_SERVER['DOCUMENT_ROOT'] . rtrim($GLOBALS['path'][0],"/"); $GLOBALS['root_script'] = "files.php"; // 表示するファイルの一覧は DOCUMENT_ROOT + REQUEST_URI $handle = @opendir($GLOBALS['comment']); $files = array(); // 全ての一覧をソートしたものが入る $files2 = array(); // ファイルのみが入る while( $target = readdir( $handle ) ) { $files[] = $target; } sort($files); foreach ( $files as $file ) { // 対象外は読み飛ばし if ( $file == '.' || $file == '..' ) { continue; } if ( $file == ".htaccess" ) { continue; } // フォルダ if ( is_dir($GLOBALS['comment'] . "/" .$file) ) { // ダウンロード用のフォルダパス $path = urlencode($_SERVER['REQUEST_URI']); if ( $_SESSION['login'] == 'yes' ) { $GLOBALS["data"] .= <<< FILES <tr> <td><a class="link" href="./{$file}/">[{$file}]</a></td> <td></td> <td><a class="link" href="./?download={$file}">ダウンロード</a></td> </tr> FILES; } else { $GLOBALS["data"] .= <<< FILES <tr> <td><a class="link" href="./{$file}/">[{$file}]</a></td> <td></td> <td></td> </tr> FILES; } } else { $files2[] = $file; } } // ファイルのタイプの取得用 $finfo = finfo_open(FILEINFO_MIME_TYPE); foreach ( $files2 as $file ) { $size = filesize($GLOBALS['comment'] . "/" . $file); $type = finfo_file($finfo, $GLOBALS['comment'] . "/" . $file); // urlencode されたファイル名の対応(元々は日本語ファイル名) $file_e = urlencode($file); // ファイル一覧用 HTML $GLOBALS["data"] .= <<< FILES <tr> <td><a href="{$file_e}">{$file}</a></td> <td>{$size}</td> <td>{$type}</td> </tr> FILES; } finfo_close($finfo); ?> <!DOCTYPE html> <html lang="ja"> <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><?= $GLOBALS['title'] ?></title> <?php require_once("std/libs.php") ?> <?php require_once("std/css.php") ?> <style> legend { font-size: 18px; padding-left: 6px; } .table-responsive td, .table-responsive th { white-space: nowrap; } #data { margin-bottom: 20px; } #comment { word-break: break-all; } #pass { padding: 20px; margin: 40px; } #system { width: 200px; margin-right: 8px; } </style> <script> <?php require_once("std/js.php") ?> $(function(){ // スマホでロード時の処理のチラつき防止用 $("#wrapper").css("visibility","visible"); $("#system_login").on("click", function(){ var formData = new FormData(); formData.append("pass", $("#system").val() ); $.ajax({ url: "./?login=yes", 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, " ") ); if ( data.login == 'yes' || data.login == 'logout' ) { location.reload(true); } }) .fail(function(jqXHR, textStatus, errorThrown ){ console.log( "status:" + textStatus ); console.log( "errorThrown:" + errorThrown ); }) }); // ************************************** // mmenu // ************************************** $("#mmenu_left").mmenu({ navbar: { title: "メニュー" }, offCanvas: { position : "left", zposition : "next" } }); }); </script> </head> <body> <div id="wrapper"> <script> // スマホでロード時の処理のチラつき防止用 $("#wrapper").css( "visibility", "hidden" ); </script> <div id="head"> <?php require_once("std/view_hamburger.php") ?> <div id="title"><?= $GLOBALS['title'] ?></div> </div> <div id="body"> <form id="frm" class="form-inline"> <div style='margin:10px;'> <a href="../">親フォルダ</a> </div> <div id="data" class="table-responsive"> <table class="table table-condensed table-hover"> <tr> <th style='width:200px;'>ファイル名</th> <th style='width:80px;'>サイズ</th> <th>MIME</th> </tr> <?= $GLOBALS["data"] ?> </table> </div> <fieldset> <legend></legend> <table class="table table-condensed"> <tr><td class="fields result error" id="erow1"><?= $GLOBALS['error'] ?></td></tr> <tr><td class="fields result error" id="erow2"></td></tr> </table> </fieldset> </form> </div> <div id="comment"> <?php if ( $_SESSION['login'] == 'yes' ) { print $GLOBALS['comment']; } else { print str_replace($_SERVER['DOCUMENT_ROOT'],"",$GLOBALS['comment']); } ?> </div> <div id="pass" class="input-group"> <input type="password" id="system" class="form-control"> <input type="button" value="管理者" id="system_login" class="btn"> </div> </div> <?php require_once("unit_menu.php") ?> </body> </html>
download.php ログインしていないと、download 関数が呼ばれる事はありません。 recursionFiles は再帰関数です。glob でフォルダが無くなるまで全ての階層を展開して、戻り値にその値を返して親でマージするので、戻って来た内容はだんだん多くなり、最後に全てのファイルのパスが取得されます。 $zip->addFile で追加する場合、第二引数で書庫内のパスを対象とするフォルダとする為、$rpath_exclude にあらかじめ対象フォルダの realpath をセットしておいて、その部分を消去して $zip->addFile に渡しています。
<?php // *********************************************** // フォルダを全て書庫化してダウンロード // *********************************************** function download() { $_GET['download'] = str_replace('/','',$_GET['download']); $_GET['download'] = str_replace('..','',$_GET['download']); $_GET['download'] = str_replace('.','',$_GET['download']); $rpath = $_SERVER['DOCUMENT_ROOT'] . rtrim($GLOBALS['path'][0],"/") . "/" . $_GET['download']; $rpath_exclude = $rpath . "/"; if ( rtrim($GLOBALS['path'][0],"/") == '' ) { print "REQUEST_URI is Incorrect"; } // ファイルは対象外(存在チェックも行う) if ( !is_dir($rpath) ) { print rtrim($GLOBALS['path'][0],"/") . "/" . $_GET['download'] . " not found or not dir"; return false; } // *********************************************** // readfile 用、バッファ解除 // *********************************************** ob_end_clean(); // *********************************************** // 対象フォルダ名 // *********************************************** $target_dir = $rpath; // *********************************************** // 書庫ファイル名 // *********************************************** $zipname = basename( $target_dir ); // *********************************************** // 一時ファイルを作成 ( temp/oooooo.tmp ) // *********************************************** $file = tempnam( sys_get_temp_dir(), "zip" ); // *********************************************** // ZIP 書庫作成 // *********************************************** $zip = new ZipArchive(); $zip->open($file, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE ); $targets = recursionFiles( $target_dir ); foreach( $targets as $target ) { $zip->addFile( $target, str_replace($rpath_exclude,"", $target) ); } $zip->close(); // *********************************************** // ダウンロードさせる為の処理 // *********************************************** header("Content-Type: application/zip"); header("Connection: close"); header("Content-Length: " . filesize($file)); header("Content-Disposition: attachment; filename=\"{$zipname}.zip\""); readfile($file); // *********************************************** // 一時ファイルを削除 // *********************************************** unlink($file); return true; } // *********************************************** // 再帰によるファイル一覧作成 // *********************************************** function recursionFiles( $target ) { $files = glob( "{$target}/*" ); $result = array(); foreach ( $files as $file ) { // ファイル if (is_file($file)) { if ( basename($file) != "files.php" ) { $result[] = $file; } } // フォルダ else { $result = array_merge($result, recursionFiles($file)); } } return $result; } ?>
|
【PHP + WEBアプリの最新記事】
- PHP : $.ajax でアップロード( 画像限定 ) / ファイルアップロード ver.3
- 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 をインストール
- 超簡易掲示板 : 保存タイプは CSV
- PHP による『超簡易掲示板』 / アプリケーションからの POST 検証用
- PHP : 既存 GD 関連ライブラリで、背景をグラデーション(2)
- PHP : 既存 GD 関連ライブラリで、背景をグラデーション
- PHP : 入力値のデバッグ
- PHP : ImageMagick : 背景が透過する画像を作成
- PHP雛型(2会話DB更新処理) : MySQL、XMLHttpRequest、XML、JSON、Canvas
- PHP をテストする為の初心者用フォーム