ダウンロードカウンター言語目次
 Japanese [日本語]  
 English [英語]  
 Korean [韓国語]  
 Simplified Chinese [简体中文]  
 Traditional Chinese [繁體中文]  
 Español [スペイン語]  
 Français [フランス語]  
 Português [ポルトガル語]  
  Arabic العربية [アラビア語]  
 Deutsch [ドイツ語]  
 Italiano [イタリア語]  
 Russian [ロシア語]  
 Turkish [トルコ語]  
 Hindi [ヒンディー語]  
 Vietnamese [ベトナム語]  
 Thai [タイ語]  
 Dutch [オランダ語]  
 Indonesian [インドネシア語]  
 Malay [マレー語]  
 Filipino [フィリピン語]  
 Swedish [スウェーデン語]  
 Norwegian [ノルウェー語]  
 Danish [デンマーク語]  
 Finnish [フィンランド語]  
 Polish [ポーランド語]  
 Czech [チェコ語]  
 Hungarian [ハンガリー語]  
 Greek [ギリシャ語]  
 Romanian [ルーマニア語]  

ダウンロードカウンター
Download Counter
ダウンロード履歴閲覧プログラム
= PHP コードをダウンロードして設置 =
Sample Download Counter

始めに

Webページのユーザーがプログラムなどをダウンロードして使用した際に、そのダウンロード数を知ることができるプログラムの紹介です。 ページ上にダウンロードカウンタを設置することが可能で、サイト管理者はブラウザ上でダウンロード履歴を簡単に確認することもできます。

ページに設置したサンプル
総ダウンロード数:1865[今日:23 昨日:76
ブラウザーで開いたサンプル
*ダウンロードリンクを設置したページで、ファイルの保存を促すメッセージが表示され後、ダウンロードをせずに閉じてもダウンロードとしてカウントされます。これは、リンクをクリックした数をカウントしているためです。
ダウンロード

このページから、プログラムを圧縮した「zip」ファイルをダウンロードし、ご自身のサイトに設置してください。ファイル名は「count.php」としていますが変更も可能です。

コードの改変、ページデザインの変更など、ご利用は全て自由です。

コードを書き換えて新しい機能を追加したり、デザインを変更したりして、わかりやすく使いやすいページにしてご利用ください。

 PHPプログラムのダウンロード

設置について

ダウンロードした「count.php.zip」ファイルを解凍すると、「count.php」というファイルが作成されます。「download_history」などのディレクトリを作って保存してください。

「zip」ファイルに入っているのは「count.php」というファイルが一つのみで、管理者用の「ログイン画面」は自動的に生成されます。

設定について

主な設定方法です。これらの主な部分は PHP ファイルの中にも記載してあります。

  1. パスワードの設定について
    1. 管理者用のページではパスワードの設定が必要です。
    2. 初期設定のパスワードは「admin」ですが、任意の文字列に変えてください。
    3. パスワードが必要なページへの外部からのアクセスを防ぐには、できるだけ強力なパスワードを設定してください。
  2. ダウンロードの対象とするファイルの設定
    1. 「$targetFiles = array()」の部分の設定を完了させてください。
    2. 「'1' => 'ご自身のURL/ファイル名.zip',」などの部分です。
  3. ログファイルを保存するためのディレクトリ
    1. 履歴を記録するログファイルを保存するために、「log」というディレクトリがリモートサーバーに必要になります。
    2. このプログラムでは、初めてアップロードした際に「log」というディレクトリが自動的に生成されます。ただし、「ディレクトリがない」などのメッセージが出た場合は別途作成しアップロードしてください。
  4. 初めてアップロードした際の履歴表示について
    1. 初めてアップロードした際の履歴表示に、「日付」と、数字の「0」が表示されることがあります。
    2. これは、自動生成された「log」ディレクトリの中に、アップロードした日付が入った「count_1.log」などのログファイルも同時に生成されるためです。
    3. これが気になる場合は、リモートサーバーにアクセスして「count_1.log」などのファイルをダウンロードし、データを削除してアップロードしてください。
    4. ただし、「日付」と「0」が入った状態は、いつカウンターを始動させたかの履歴にもなるかも知れません。その日にダウンロードがあればカウントアップします。
  5. 管理者閲覧ページでの表示について
    1. 管理者が閲覧するページの表示では、当該ファイルの表示に URL を含めるか、ファイル名のみを表示するかの選択をすることができます。
    2. 1 ページに複数の履歴テーブルを設置した場合、「$targetFiles = array()」で設定した並びのままとするか、新しいログが発生した日付順にソートするかの選択ができます。
  6. ページデザイン、CSSなど
    1. ページデザイン、CSSなどは適宜調整し、見やすいページにしてご利用ください。
    2. 一時、CSSは外部ファイルとしていましたが、CSSを変更する際タグを参照しながら作業ができるよう同じページ内に記載しました。
  7. ダウンロードリンクを設置するページでの設定の仕方
    1.  通常、ダウンロードの <a> タグは次のように書きます。
      <a href="/download_history/sample.zip" download="ダウンロードした際のファイル名.zip">[任意の文字列]</a>
    2. このプログラムでは、ダウンロードの <a> タグを次のような書き方にします。
    3. [例]コピー
      <a href="/download_history/count.php?download=1" download="ダウンロードした際のファイル名.zip" target="_blank">[任意の文字列]</a>
    4. 「download=1"」の数字を、「$targetFiles = array()」で設定した数字に合わせます。この設定でダウンロードするファイルを参照します。
    5. パスはご自身のページに合わせてください。
    6. ダウンロードリンクを設置したページのアップロードは、「$targetFiles = array()」を設定したファイル(ここでの例は「count.php」)のアップロードを済ませてからにしてください。
  8. ダウンロードリンクを設置したページなどで、一行で履歴を表示するためのコード
    1. 次のような JavaScript を作り、表示させるページに設置します。
    2. [例]コピー
      <script type="text/javascript" src="/download_history/count.php?dsp_count=1&day_dsp=on"></script>
    3. 「dsp_count=1」の数字を「$targetFiles = array()」で設定した数字に合わせてください。
    4. 「&day_dsp=on」を削除すると、「今日・昨日」の表示のない「総数」のみの表示となります。
    5. 総ダウンロード数:1865[今日:23 昨日:76
      総ダウンロード数:1865
    6. パスはご自身のページに合わせてください。
拡張設定について

複数のテーブルを表示した場合、このプログラムの初期設定では最終更新時間の新しい順にソートしていますが、総ダウンロード数でソートしたいと考えた場合は、"total_downloads.php" などのファイルを新たに作り、次の部分を差し替えてください。

  1. コメントの変更
    下記の部分のコメントを差し替えてください。
    // ページに複数のテーブルを表示した場合、元の配列を置き換えて新しいログの順に並べ替えるかどうかの選択・設定
  2. 差し替えるコメントをコピー
    // ページに複数のテーブルを表示した場合、元の配列を置き換えてダウンロードの総数が多い順に並べ替えるかどうかの選択・設定
  3. コードとコメントの変更
    下記の部分のコードとコメントを差し替えてください。一つのブロックとして考えてくださって結構です。
    // ファイルパスとその最終更新日を取得(新しい順にソート)
    $filePathsAndDates = array();
    foreach ($filePath as $key => $path) {
        if (file_exists($path)) {
            $filePathsAndDates[$key] = filemtime($path);
        } else {
            // このエラーはログに出力し、処理を続行するか中断するかを決定
            echo "エラー: ファイルが存在しません - $path<br>";
        }
    }
    
    // 最終更新日で降順ソート(新しい日付が先に来るように)
    arsort($filePathsAndDates);
    
    // ソートされたファイルパスの配列を再構築
    $sortedFilePaths = array();
    foreach ($filePathsAndDates as $key => $date) {
        $sortedFilePaths[$key] = $filePath[$key];
    }
  4. 差し替えるコードとコメントをコピー
    // 総ダウンロード数を格納する配列
    $totalDownloads = array();
    
    // ファイルパスとその総ダウンロード数を取得
    foreach ($filePath as $key => $path) {
        if (file_exists($path)) {
            $line = file($path);
            $total = 0;
    
            // 各行のダウンロード数を合計
            foreach ($line as $val) {
                $valArray = explode(',', $val);
                $total += trim($valArray[1]);
            }
    
            // 総ダウンロード数を配列に格納
            $totalDownloads[$key] = $total;
        } else {
            // このエラーはログに出力し、処理を続行するか中断するかを決定
            echo "エラー: ファイルが存在しません - $path";
        }
    }
    
    // 総ダウンロード数で降順ソート
    arsort($totalDownloads);
    
    // ソートされたファイルパスの配列を再構築
    $sortedFilePaths = array();
    foreach ($totalDownloads as $key => $total) {
        $sortedFilePaths[$key] = $filePath[$key];
    }
  5. ファイルの新設と設置
    1. 複数のページを作る場合、内容を追加しながら統一して設定する項目でのミスを防ぐために、下記の部分のコードを外部ファイルとし、現在実装してある部分に別のコードで読み込みます。外部フィルを "config.php" などの名称で作ってください。
    // ダウンロードするファイルの設定。複数ある場合は、「'2'」「'3'」「'4'」のように追加。「'0'」も有効
    // http: または https: から記述
    $targetFiles = array(
        '1' => 'ご自身のURL/ファイル名.zip',
        '2' => 'ご自身のURL/ファイル名.pdf',
        '3' => 'ご自身のURL/ファイル名.pdf', 
        '4' => 'ご自身のURL/ファイル名.pdf',
    );
  6. "config.php" とする部分のサンプルをコピー
    <!doctype html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>DownloadHistory</title>
    <meta name="robots" content="NOINDEX,NOFOLLOW">
    </head>
    <body>
    <?php
    // この部分のみを外部ファイルとし、使用するページ内に「include __DIR__ . '/config.php';」で読み込む
    // ダウンロードするファイルの設定。複数ある場合は、「'2'」「'3'」「'4'」のように追加。「'0'」も有効
    // http: or https: から記述
    $targetFiles = array(
        '1' => 'ご自身のURL/ファイル名.zip',
        '2' => 'ご自身のURL/ファイル名.pdf',
        '3' => 'ご自身のURL/ファイル名.pdf', 
        '4' => 'ご自身のURL/ファイル名.pdf',
    );
    ?>
    </body>
    </html>
    
  7. 外部ファイルを読み込むコードと設置場所
    1. " config.php " などの名称で作ったファイルを下記の場所に " include __DIR__ . '/config.php'; " のコードで読み込みます。
    2. 下記部分をコメントアウトするか、削除し、" include __DIR__ . '/config.php'; " のコードに置き換えてください。
    //$targetFiles = array(
    //    '1' => 'ご自身のURL/ファイル名.zip',
    //    '2' => 'ご自身のURL/ファイル名.pdf',
    //    '3' => 'ご自身のURL/ファイル名.pdf', 
    //    '4' => 'ご自身のURL/ファイル名.pdf',
    //);
  8. 置き換えるコードをコピー
    include __DIR__ . '/config.php';
* プログラム内の「font-family」は、必要に応じてご自身のサイトに合わせて調整してください。
《 ダウンロードカウンター作成 PHP コード 》
保存する場合の拡張子は「.php」です。

<?php
//***************************************************************************************************
// ダウンロードカウンター・ダウンロード履歴閲覧PHPプログラム
// 【みんなの知識 ちょっと便利帳】
// https://www.benricho.org/Tips/download_history/
// Released: January 22, 2024
//
// 概要:
//  このプログラムは、ファイルダウンロードの履歴を追跡するためのシステムで、ユーザー認証機能も備えています。
//  入力データのサニタイズ、ログファイルの作成、ダウンロード統計の表示などの機能が組み込まれています。
//  コードの改変、ページデザインの変更など、ご利用は全て自由です。 
//
// ご注意:
//  ダウンロードリンクを設置したページをアップロードする前に、このファイルの「$targetFiles = array()」の部分の設定を済ませ、
//  かつ、ダウンロードリンクを設置したページよりも先にこのページをアップロードしてください。
//  そうしないと、ユーザーがダウンロードを試みた際にダウンロードできない可能性があります。
//  それは、ダウンロードの対象とするファイルをこのページで設定・参照しているためです。
//
// 設定など:
//  ① パスワードは「admin」としていますが、任意の文字列に変更してください。
//  ② ログファイルを格納するための「log」というディレクトリは、初めてアップロードした際に自動生成されます。
//      ただし、「ディレクトリがない」などのメッセージが出た場合は、別途アップロードしてください。
//  ③ 初めてアップロードした際、履歴表示に「日付」と、数字の「0」が表示されます。
//      これは、自動生成された「log」ディレクトリの中に、アップロードした日付が入った「count_1.log」などのログファイルも同時に生成されるためです。
//      これが気になる時は、リモートサーバーにアクセスして「count_1.log」などのファイルをダウンロードし、データを削除してアップロードしてください。
//  ④ 履歴表示で、ページに複数のテーブルを表示した場合、[$targetFiles = array()]の設定で、①設定した配列のままとするか、②日付の新しい順にするかの選択ができます。
//  ⑤ 履歴表示で、1)当該ファイルの表示にドメインを含めるか、2)ファイル名のみの表示かの選択ができます。
//
//【ダウンロードリンクを設置するページでのリンクの書き方】
// [例]<a href="/download_history/count.php?download=1" download="ダウンロードした際のファイル名.zipzip" target="_blank">[任意の文字列]</a>
//     ①「download=1"」の数字を、「$targetFiles = array()」で設定した数字に合わせてください。
//     ② パスはご自身のページに合わせてください。
//
//【ダウンロードリンクを設置したページなどに、一行で履歴を表示するためのコード(JavaScript)】
// [例]<script type="text/javascript" src="/download_history/count.php?dsp_count=1&day_dsp=on"></script>
//     ①「dsp_count=1」の数字を「$targetFiles = array()」で設定した数字に合わせてください。
//     ②「&day_dsp=on」を削除すると、「今日・昨日」の表示のない「総数」のみの表示となります。
//     ③ パスはご自身のページに合わせてください。
//***************************************************************************************************

// ダウンロードするファイルの設定。複数ある場合は、「'2'」「'3'」「'4'」のように追加。「'0'」も有効
// http: または https: から記述
$targetFiles = array(
    '1' => 'ご自身のURL/ファイル名.zip',
    '2' => 'ご自身のURL/ファイル名.pdf',
    '3' => 'ご自身のURL/ファイル名.pdf', 
    '4' => 'ご自身のURL/ファイル名.pdf',
);

// HTML出力のための文字エンコーディングを設定
header("Content-Type: text/html; charset=utf-8");

// カウント履歴を表示するページでの文字コード
// Shift-jis は「SJIS」、EUC-JP は「EUC-JP」と設定
$encodingType = 'UTF-8';

// ユーザー認証情報やその他の設定を定義
$userid = 'admin';   // ユーザーID(admin部分)を任意の文字列で
$password = 'admin'; // パスワード(admin部分)を任意の文字列に変更してください
$hashedPassword = password_hash($password, PASSWORD_DEFAULT); // パスワードのハッシュ関数を使用して、ハッシュ値を生成
$dataLogDir = 'log/'; // logディレクトリは、このプログラムでは自動生成されます。生成されない場合は「log」というディレクトリを別途アップロードしてください

// ファイル名表示時にドメインを含めるかどうかの選択・設定
$includeDomain = 1;  // 1: ドメイン名を含めた表示, 0: ファイル名のみの表示

// ページに複数のテーブルを表示した場合、元の配列を置き換えて新しいログの順に並べ替えるかどうかの選択・設定
$sortTables = 1;  // 1: ソートする, 0: ソートしない

$dir = 'log'; // ログファイルやダウンロード履歴の格納先ディレクトリ

// 自サイトのドメインを取得
$domain = $_SERVER['HTTP_HOST'];

// セッション管理: セッションのハイジャック対策とsession_set_cookie_params()の使用
session_set_cookie_params(0, '/', $domain, true, true); // HttpOnlyおよびSecureフラグを設定
session_start();
if (!isset($_SESSION['auth'])) {
    $_SESSION['auth'] = FALSE;
}

// パスワードのハッシュ化: password_needs_rehash()の使用
if (password_needs_rehash($hashedPassword, PASSWORD_DEFAULT)) {
    $newHashedPassword = password_hash($password, PASSWORD_DEFAULT);
    // データベースなどに新しいハッシュ値を保存する
}

// ディレクトリが存在しない場合は作成する
if (!is_dir($dir)) {
    if (mkdir($dir, 0755, true)) {
    } else {
        // ディレクトリの作成に失敗した場合の表示
        echo '「' . $dataLogDir . '」ディレクトリを作成し、別途アップロードしてください。';
    }
}

// ログディレクトリが書き込み可能か確認
if (!is_writable($dataLogDir)) {
    die('「' . $dataLogDir . '」ディレクトリが存在しないか、書き込み権限がありません。ディレクトリを作成し、パーミッションを適切に設定してください(例: 755)。');
}

// 基準日と昨日の日付を取得
$baseDay = date("Y/m/d");
$yesterday = date("Y/m/d", strtotime("-1 day"));

// 日付から曜日を取得するための関数
function getDayOfWeek($date)
{
    $dayOfWeek = date('w', strtotime($date));
    $weekDays = array('日', '月', '火', '水', '木', '金', '土');
    return $weekDays[$dayOfWeek];
}

// ターゲットファイルごとにファイルパスを設定し、存在しない場合はログファイルを作成
foreach ($targetFiles as $key => $val) {
    $filePath[$key] = $dataLogDir . "count_" . $key . ".log";

    // ログファイルが存在しない場合は作成する
    if (!file_exists($filePath[$key])) {
        createLogFile($filePath[$key]);
    }
}

// ファイルパスとその最終更新日を取得(新しい順にソート)
$filePathsAndDates = array();
foreach ($filePath as $key => $path) {
    if (file_exists($path)) {
        $filePathsAndDates[$key] = filemtime($path);
    } else {
        // このエラーはログに出力し、処理を続行するか中断するかを決定
        echo "エラー: ファイルが存在しません - $path<br>";
    }
}

// 最終更新日で降順ソート(新しい日付が先に来るように)
arsort($filePathsAndDates);

// ソートされたファイルパスの配列を再構築
$sortedFilePaths = array();
foreach ($filePathsAndDates as $key => $date) {
    $sortedFilePaths[$key] = $filePath[$key];
}

// ソートするかどうかの条件分岐
$filePath = ($sortTables) ? $sortedFilePaths : $filePath;

// クライアントにJavaScriptのコードを返す(ダウンロード数を動的に表示)
if (isset($_GET['dsp_count'])) {
    header("Content-type: application/x-javascript");

    // JavaScriptファイルとしてのヘッダーを設定
    if (!preg_match("/^[0-9]+$/", $_GET['dsp_count'])) {
        echo "document.write(\"パラメータは半角数字で\")";
        exit();
    }

    $dspCountNo = $_GET['dsp_count'];
    if (!file_exists($filePath[$dspCountNo])) {
        createLogFile($filePath[$dspCountNo]);
    }

    $line = file($filePath[$dspCountNo]);
    $total = 0;
    $todayCount = 0;
    $yesterdayCount = 0;

    foreach ($line as $val) {
        $valArray = explode(',', $val);
        $total += trim($valArray[1]);
        if (strpos($valArray[0], $baseDay) !== false) {
            $todayCount = trim($valArray[1]);
        }
        if (strpos($valArray[0], $yesterday) !== false) {
            $yesterdayCount = trim($valArray[1]);
        }
    }

    // 日付表示オプションがONの場合、日付を含めた表示
    if (isset($_GET['day_dsp']) && $_GET['day_dsp'] == 'on') {
        $countDsp = <<<EOF
document.write('<div class="counter_inpage">総ダウンロード数: <strong>{$total}</strong> [<span class="count_today">今日 : <strong>{$todayCount}</strong></span>  <span class="count_yesterday">昨日 : <strong>{$yesterdayCount}</strong></span>]</div>')
EOF;
    } else {
        // 日付表示オプションがOFFの場合、総ダウンロード数のみ表示
        $countDsp = <<<EOF
document.write('<p class="counter_inpage">総ダウンロード数: <strong>{$total}</strong></p>')
EOF;
    }

    // 文字エンコーディングがUTF-8以外の場合、変換
    if ($encodingType != 'UTF-8') $countDsp = mb_convert_encoding($countDsp, "$encodingType", 'UTF-8');
    echo $countDsp;

    exit();
}

// ファイルのダウンロードが要求された場合の処理
if (isset($_GET['download'])) {
    $fileId = $_GET['download'];

    // ファイルIDが数値でない場合または存在しないファイルIDの場合は終了
    if (!preg_match("/^[0-9]+$/", $fileId) || !isset($filePath[$fileId])) {
        exit('パラメータの数値が違っています');
    }

    // ファイルを開いてロック
    $fp = fopen($filePath[$fileId], "rb+");
    if (!$fp) {
        exit('ファイルのオープンに失敗しました');
    }

    flock($fp, LOCK_EX);

    // ログファイルを読み込んで配列に格納
    $line = array();
    while (($data = fgets($fp)) !== false) {
        $line[] = $data;
    }

    // ファイルを切り詰めて先頭に新しい日付の行を追加
    ftruncate($fp, 0);
    rewind($fp);

    if (strpos($line[0], $baseDay) === false) {
        $writeLine = $baseDay . ',1' . "\n";
        fwrite($fp, $writeLine);
    }

    foreach ($line as $val) {
        if (strpos($val, $baseDay) !== false) {
            $valArray = explode(',', $val);
            $valArray[1] = rtrim($valArray[1], "\n") + 1;
            $val = $valArray[0] . ',' . $valArray[1] . "\n";
        }
        fwrite($fp, $val);
    }

    // フラッシュしてロック解除
    fflush($fp);
    flock($fp, LOCK_UN);

    // ファイルを閉じる
    fclose($fp);

    // クリアされたバッファを出力
    ob_end_clean();

    // ファイルのダウンロードを実行
    header("Location: {$targetFiles[$fileId]}");
    exit();
} else {
    // セッションを開始し、ログアウトが要求された場合はセッション破棄
    session_start();
    if (isset($_GET['logout'])) {
        $_SESSION = array();
        session_destroy();
    }

    $loginError = '';

    if (!isset($_SESSION['auth'])) {
        $_SESSION['auth'] = FALSE;
    }

    // パスワードのハッシュ関数を使用して、ハッシュ値を生成
    // ログイン時の処理
    if (isset($_POST['userid']) && isset($_POST['password'])) {
        // ハッシュ値を比較して認証
        if ($_POST['userid'] === $userid && password_verify($_POST['password'], $hashedPassword)) {
            $oldSid = session_id();
            session_regenerate_id(TRUE);

            if (version_compare(PHP_VERSION, '5.1.0', '<')) {
                $path = session_save_path() != '' ? session_save_path() : '/tmp';
                $oldSessionFile = $path . '/sess_' . $oldSid;

                if (file_exists($oldSessionFile)) {
                    unlink($oldSessionFile);
                }
            }

            $_SESSION['auth'] = TRUE;
        } else {
            // 認証失敗時の処理
            $_SESSION['auth'] = FALSE;
            $loginError = '<div style="text-align: center; color: crimson;">ユーザーID、もしくはパスワードに誤りがあります。</div>';
        }
    }

    // 認証が成功していない場合、ログイン画面を表示
    if ($_SESSION['auth'] !== TRUE) {
        ?>
        <!DOCTYPE html>
        <html lang="ja">
        <head>
            <meta charset="utf-8">
            <meta name="robots" content="NOINDEX,NOFOLLOW">
            <title>ダウンロード履歴 ログイン画面</title>
            <!-- ログイン画面のスタイル(必要に応じて変更可能)-->
            <style>
                body {
                    font-family: Arial, sans-serif;
                    background-color: #f4f4f4;
                    margin: 0px;
                    padding: 0px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    height: 100vh;
                }
                form {
                    background-color: #fff;
                    padding: 20px;
                    border-radius: 8px;
                    box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
                }
                label {
                    display: block;
                    margin-bottom: 8px;
                }
                input {
                    font-size: 18px; 
                    width: 100%;
                    padding: 8px;
                    margin-bottom: 16px;
                    box-sizing: border-box;
                }
                button {
                    font-size: 16px;
                    background-color: #4caf50;
                    color: #fff;
                    padding: 10px;
                    border: none;
                    border-radius: 4px;
                    cursor: pointer;
                }
                .logintitle {
                    text-align: center;
                    font-size: 18px;
                    font-weight: bold;
                }
                .logininfo {
                    text-align: center;
                }
                .passwordshow {
                    font-size: 14px;
                    font-weight: bold;
                    color: darkgray;
                    text-align: center;
                }
                .center-container {
                    display: inline-block;
                    margin: 0 5px 0 0;
                }
            </style>
        </head>
        <body>
            <div id="login_form">
                <form action="<?php echo $fileName; ?>?mode=download" method="post">
                    <p class="logintitle">【ダウンロード履歴の閲覧】</p>
                    <?php if (isset($loginError)): ?>
                        <!-- $loginError変数が設定されている場合にエラーメッセージを表示 -->
                        <p style="color: crimson;"><?php echo $loginError; ?></p>
                    <?php endif; ?>
                    <label for="userid">ユーザーID:</label>
                    <input type="text" id="userid" name="userid" required>
                    <label for="password">パスワード:</label>
                    <input type="password" id="password" name="password" required>
                    <?php
                        // $showPasswordがパスワードを表示するかどうかを決定するPHP変数であると仮定しています
                        echo '<label class="passwordshow" for="showPassword">[ パスワードを表示する ]<div class="center-container"><input type="checkbox" id="showPassword" onchange="togglePasswordVisibility()" ' . ($showPassword ? 'checked' : '') . '></div></label>';
                    ?>
                    <button type="submit" name="login_submit">ログイン</button>
                </form>
            </div>
                <!-- パスワードの表示・非表示を制御 -->
                  <script>
                    function togglePasswordVisibility() {
                      var passwordInput = document.getElementById('password');
                      var showPasswordCheckbox = document.getElementById('showPassword');

                      if (showPasswordCheckbox.checked) {
                        // チェックを入れるとパスワードが表示されます
                        passwordInput.type = 'text';
                      } else {
                        // チェックを外すとパスワードが非表示になります
                        passwordInput.type = 'password';
                      }
                    }
                  </script>
        </body>
        </html><?php
        exit();
    } else {
        // ログイン済みの場合、ダウンロード履歴ページを表示
        ?>
        <!DOCTYPE html>
        <html lang="ja">
        <head>
            <meta charset="utf-8">
            <meta name="robots" content="NOINDEX,NOFOLLOW">
            <title>ダウンロード履歴</title>
            <!-- ダウンロード履歴閲覧部スタイル(必要に応じて変更可能)-->
            <style>
                body {
                    font-family: 'Hiragino Kaku Gothic ProN', 'ヒラギノ角ゴ ProN W3', Meiryo, メイリオ, Osaka, 'MS PGothic', arial, helvetica, sans-serif;
                }
                .log_title {
                    font-size: 16px;
                    font-weight: bold;
                    color: brown;
                    margin: 0px 0px 15px 10px;
                }
                .get_url {
                    font-size: 13px;
                    font-weight: bold;
                    padding: 8px 0;
                    color: brown;
                    background-color: lightgoldenrodyellow;
                }
                .log_table{
                    float:left;
                    width: 270px;
                    border: #CCC 1px solid;
                    border-radius: 5px;
                    margin: 0px 0px 5px 10px;
                    padding: 0px 5px 5px 5px;
                    word-break: break-all;
                }
                table {
                    width: 100%;
                    border-collapse: collapse;
                }
                td,
                th {
                    padding: 5px 10px;
                    border: 1px solid #999;
                    text-align: right;
                    font-size: 90%;
                }
                th {
                    background: lavenderblush;
                    text-align: center;
                    font-weight: normal;
                }
                .tableheader {
                    background: lavender;
                    text-align: center;
                    font-weight: bold;
                    white-space: nowrap;
                }
                .total{
                    float:left;
                    margin: -25px 0px 0px 10px;
                }
                .counter_inpage{
                    margin: 15px 0px 8px 0px;
                }
                .bold{
                    font-weight: bold;
                }
            </style>
        </head>
        <body>
            <div class="log_title">【ダウンロード履歴】 【<a href="?logout=true">ログアウト</a>】</div> 
            <?php foreach($filePath as $key => $val){ ?>                      
                <div class="log_table">         
                  <div class="get_url"><?php echo $includeDomain ? $targetFiles[$key] : basename($targetFiles[$key]); ?></div>
                    <table align="center">
                        <tr>
                            <th class="tableheader">日付</th>
                            <th class="tableheader">&nbsp;&nbsp;ダウンロード&nbsp;&nbsp;</th>
                        </tr>
                        <?php
    $totalDownload = 0;

    // ファイルが存在する場合にのみ読み込む
    if (file_exists($val)) {
        $line = file($val);
        foreach ($line as $lineVal) {
            $lineArray = explode(',', $lineVal);

            // $lineArray[1] の値が数値であるか確認
            $numericValue = filter_var($lineArray[1], FILTER_VALIDATE_FLOAT);
            if ($numericValue !== false) {
                $totalDownload += $numericValue;
                ?>
                <tr>
                    <th nowrap><?php echo $lineArray[0] . ' (' . getDayOfWeek($lineArray[0]) . ')'; ?></th>
                    <td class="bold" nowrap><?php echo $lineArray[1]; ?></td>
                </tr>
                <?php
            }
        }
    }
                        ?>
                        <tr>
                            <th colspan="2" class="bold">総ダウンロード数:<?php echo $totalDownload;?></th>
                        </tr>
                    </table>
                </div>
            <?php
            }
        }
    }
?>
        </body>
        </html><?php
// 配列内のすべての要素に対してサニタイズを行う関数
function sanitize($arr)
{
    // 配列である場合、再帰的にサニタイズを適用
    if (is_array($arr)) {
        return array_map('sanitize', $arr);
    }
    // 文字列内のNULL文字を取り除く
    return str_replace("\0", "", $arr);
}

// ログファイルが存在しない場合は新しく作成
function createLogFile($filePath)
{
    $baseDay = date("Y/m/d");
    $fp = fopen($filePath, "a+b");

    if ($fp) {
        flock($fp, LOCK_EX);
        ftruncate($fp, 0);
        rewind($fp);
        fwrite($fp, "$baseDay,0");
        fflush($fp);
        flock($fp, LOCK_UN);
        fclose($fp);

        // ファイルのパーミッションを設定
        chmod($filePath, 0666);
    } else {
    }
}
ここまでで、「ダウンロードカウンター・ダウンロード履歴閲覧プログラム」のための PHP コードの紹介は終了です。ご活用いただければ幸いです。
ご利用になられてのご感想などをお寄せいただければ幸いです。なお、ご質問にはお答えすることができませんのでご了承ください。

おすすめサイト・関連サイト…

Last updated : 2024/06/29