Download Counter Language Table of Contents
 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 [ルーマニア語]  

다운로드 카운터
다운로드 이력 브라우징 프로그램
= PHP 코드 다운로드 및 설치=
Sample Download Counter

처음에

웹페이지 사용자가 프로그램을 다운로드하여 사용할 때 다운로드 횟수를 알 수 있는 프로그램에 대한 소개입니다. 페이지에 다운로드 카운터를 설정할 수 있으며, 사이트 관리자도 브라우저에서 다운로드 내역을 쉽게 확인할 수 있습니다.

【페이지에 설치한 샘플】
총 다운로드 수: 1865[오늘:23 어제:76
브라우저에서 열었을 때의 샘플
* 다운로드 링크를 설정한 페이지에서 파일을 저장하라는 메시지가 나온 후 다운로드를 실행하지 않고 닫아도 다운로드 수로 계산됩니다. 이는 링크를 클릭한 수를 세었기 때문입니다.
다운로드

이 페이지에서 프로그램을 압축한 "zip" 파일을 다운로드하여 자신의 사이트에 설치하십시오. 파일명은 「count.php」로 하고 있습니다만 변경도 가능합니다.

코드의 변경, 페이지 디자인의 변경 등, 이용은 모두 자유롭습니다.

'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. 한 페이지에 여러 개의 히스토리 테이블을 설치한 경우 "$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<br>";
         }
    }
    
    // 총 다운로드 수로 내림차순 정렬
    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:" 또는 "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';
《 다운로드 카운터를 생성하는 PHP 코드 》
저장할 때 확장자는 '.php'입니다.

<?php
//***************************************************************************************************
// 카운터 다운로드/다운로드 내역 보기 PHP 프로그램
// “모두의 지식, 조금 유용한 책”
// “みんなの知識 ちょっと便利帳”
// https://www.benricho.org/Tips/download_history/
// 출시일: 2024년 1월 22일
//
// 개요 (overview):
// 이 프로그램은 파일 다운로드 내역을 추적하는 시스템으로, 사용자 인증 기능도 포함되어 있습니다.
// 내장된 기능에는 입력 데이터 삭제, 로그 파일 생성, 다운로드 통계 보기가 포함됩니다.
// 코드 수정, 페이지 디자인 변경 등 자유롭게 사용하실 수 있습니다.
//
// 참고하세요 (Please note):
// 다운로드 링크가 포함된 페이지를 업로드하기 전, 이 파일의 "$targetFiles = array()" 부분을 설정하고,
// 그리고 다운로드 링크가 있는 페이지보다 먼저 이 페이지를 업로드해주세요.
// 그렇지 않으면 사용자가 다운로드를 시도할 때 다운로드하지 못할 수 있습니다.
// 다운로드할 파일을 이 페이지에서 설정하고 참조하기 때문입니다.
//
// 설정 등 (Settings etc):
// ① 비밀번호는 "admin" 이지만, 원하는 문자열로 변경해주세요.
// ② 최초 업로드 시 로그 파일을 저장하기 위한 "log"라는 디렉터리가 자동으로 생성됩니다.
// 단, "디렉터리 없음" 등의 메시지가 나오는 경우에는 별도로 업로드해주시기 바랍니다.
// ③ 처음 업로드하는 경우 기록 표시에 "날짜"와 숫자 "0"이 표시됩니다.
// 자동으로 생성된 "log" 디렉터리에 업로드 날짜가 포함된 "count_1.log" 등의 로그 파일도 동시에 생성되기 때문입니다.
// 이 부분이 걱정된다면 원격 서버에 접속하여 "count_1.log" 등의 파일을 다운로드 받아 데이터를 삭제한 후 업로드해주세요.
// ④ 히스토리 표시에서 여러 테이블을 한 페이지에 표시할 때 [$targetFiles = 배열]을 설정하여 ① 설정된 배열을 유지할지, ② 시간순으로 표시할지를 선택할 수 있습니다.
// ⑤ 기록 표시에서는 1) 파일 표시에 도메인을 포함할지, 2) 파일 이름만 표시할지 선택할 수 있습니다.
//
//[다운로드 링크가 설정된 페이지에 링크를 작성하는 방법]
// [예] <a href="/download_history/count.php?download=1" download="다운로드 시 파일명.zip" 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");

// 페이지를 표시하는 데 사용되는 문자 코드
$encodingType = 'UTF-8';

// 사용자 자격 증명 및 기타 설정 정의
$userid = 'admin'; // 사용자 ID (관리자 부분)에 임의의 문자열을 사용
$password = 'admin'; // 비밀번호 (관리자 부분)를 임의의 문자열로 변경
$hashedPassword = password_hash($password, PASSWORD_DEFAULT); // 비밀번호 해시 함수를 사용하여 해시 값을 생성
$dataLogDir = '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]);
         }
     }

     // 날짜 표시 옵션이 켜져 있으면 날짜를 포함하여 표시
     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 {
         // 날짜 표시 옵션이 꺼져 있으면 전체 다운로드 횟수만 표시
         $countDsp = <<<EOF
document.write('<p class="counter_inpage">총 다운로드 횟수: {$total}</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="ko">
        <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)): ?>
                         <!-- Display an error message if the $loginError variable is set -->
                         <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="ko">
        <head>
            <meta charset="utf-8">
            <meta name="robots" content="NOINDEX,NOFOLLOW">
            <title>다운로드 기록</title>
             <!-- 다운로드 기록 보기 섹션 스타일 (필요에 따라 변경 가능) -->
             <style>
                 body {
                     font-family: 'Hiragino Kaku Gothic ProN', 'Hiragino Kaku Gothic 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">다운로드 수</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/04/23