Programming/PHP

PHP 압축파일에 암호화 후 다운로드

고고마코드 2021. 12. 16. 00:17
반응형

PHP 파일 다운로드 시 압축파일로 만들기 / 압축하는 파일에 암호 걸기.

PHP 7.2 이상의 환경만 가능한 방법이다. (ZipArchive::setEncryptionName를 사용하기 위해서)

압축파일만 생성할 거라면(암호화 X) PHP 5.2 이상의 환경에서도 사용 가능하다.

압축파일 해제를 원하면 링크(PHP 압축파일 해제 후 다운로드)를 참고하세요.


사용할 함수 이해하기

  • ZipArchive::open(filename, flag) : 압축파일을 연다.

    • filename : 열려는 압축 파일의 이름
    • flag : 압축 파일 모드 (overwrite, create, readonly, excel, checkcons)
  • ZipArchive::close : 열렸거나 새로 만든 압축파일을 닫는다.

  • ZipArchive::addFile(filepath, entryname) : 압축파일에 파일 추가하기

    • filepath : 추가할 파일의 경로
    • entryname : 추가할 때 정해줄 이름
  • ZipArchive::setPassword(password) : 파일에 비밀번호를 설정한다. (암호를 부여/해제 할 때 모두 사용)

    • password : 설정할 비밀번호
  • ZipArchive::setEncryptionName(name, method) : 입력한 이름의 파일을 찾아 암호화 한다.

    • name : 암호를 설정할 파일의 이름
    • method : 암호화 방법 (EM_AES_128, EM_AES_192, EM_AES_256, 등)

압축파일 암호화 후 다운로드

압축파일 생성을 위한 기본 세팅

$zip = new ZipArchive(); #압축파일 관련 라이브러리
$directory_file = DATA_PATH."/test"; #압축할 파일들이 있는 경로
$directory_copy = "/home/data/test/"; #압축파일이 생성될 경로

$zipfile = $directory_copy."download/pwdtest.zip"; #생성 OR 수정할 압축파일 이름

$handle = opendir($directory_file); #압축할 파일들을 찾기 위해 폴더 열기 (절대경로)

#압축파일이 이미 있다면 덮어쓰기, 없다면 압축파일 생성
$flag = (file_exists($zipfile))? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE;

$password = 'secret'; #부여할 암호 미리 정해두기

암호화 압축 진행

#압축파일 열기
if($zip->open($zipfile, $flag) === true) { 
    if (!$zip->setPassword($password)) { #압축파일에 비밀번호 설정
        echo "Set password failed";
    }

    #압축할 파일들 순서대로 탐색하기
    while ($file = readdir($handle)) { 
        $fileInfo = pathinfo($file); #파일 정보 가져오기
        $fileExt = $fileInfo['extension']; #파일의 확장자를 구함(특정 확장자만 가져오려면)

        if($fileExt == "exe" || $fileExt == "dmg") { 
            $fileName = directory_file.'/'.$file;
            $baseName = basename($fileName);

            #압축파일에 파일 추가
            if (!$zip->addFile($fileName, $baseName)) {
                throw new RuntimeException(sprintf('Add file failed: %s', $fileName));
            }

            #파일을 AES-256으로 암호화
            if (!$zip->setEncryptionName($baseName, ZipArchive::EM_AES_256)) {
                throw new RuntimeException(sprintf('Set encryption failed: %s', $baseName));
            }
        }
    }

    closedir($handle); #탐색한 폴더 닫기
}

$zip->close(); #압축파일 닫기

압축파일 다운로드

$file = "pwdtest.zip"; #다운로드 할 때 정해줄 이름
$down = $zipfile; #실제 다운로드할 파일
$filesize = filesize($down);

if(file_exists($down)) {
    header("Content-Type:application/octet-stream");
    header("Content-Disposition:attachment;filename=$file");
    header("Content-Transfer-Encoding:binary");
    header("Content-Length:".filesize($down));
    header("Cache-Control:cache,must-revalidate");
    header("Pragma:no-cache");
    header("Expires:0");
    if(is_file($down)) {
        $fp = fopen($down,"r");
        while(!feof($fp)) {
            $buf = fread($fp,8096);
            $read = strlen($buf);
            print($buf);
            flush();
        }
        fclose($fp);
    }
} else {
    #파일이 존재하지 않을 때 오류 메시지
}

압축파일 암호화 후 다운로드 전체 코드

$zip = new ZipArchive(); #압축파일 관련 라이브러리
$directory_file = DATA_PATH."/test"; #압축할 파일들이 있는 경로
$directory_copy = "/home/data/test/"; #압축파일이 생성될 경로

$zipfile = $directory_copy."download/pwdtest.zip"; #생성 OR 수정할 압축파일 이름

$handle = opendir($directory_file); #압축할 파일들을 찾기 위해 폴더 열기 (절대경로)

#압축파일이 이미 있다면 덮어쓰기, 없다면 압축파일 생성
$flag = (file_exists($zipfile))? ZIPARCHIVE::OVERWRITE : ZIPARCHIVE::CREATE;

$password = 'secret'; #부여할 암호 미리 정해두기

#압축파일 열기
if($zip->open($zipfile, $flag) === true) { 
    if (!$zip->setPassword($password)) { #압축파일에 비밀번호 설정
        echo "Set password failed";
    }

    #압축할 파일들 순서대로 탐색하기
    while ($file = readdir($handle)) { 
        $fileInfo = pathinfo($file); #파일 정보 가져오기
        $fileExt = $fileInfo['extension']; #파일의 확장자를 구함(특정 확장자만 가져오려면)

        if($fileExt == "exe" || $fileExt == "dmg") { 
            $fileName = directory_file.'/'.$file;
            $baseName = basename($fileName);

            #압축파일에 파일 추가
            if (!$zip->addFile($fileName, $baseName)) {
                throw new RuntimeException(sprintf('Add file failed: %s', $fileName));
            }

            #파일을 AES-256으로 암호화
            if (!$zip->setEncryptionName($baseName, ZipArchive::EM_AES_256)) {
                throw new RuntimeException(sprintf('Set encryption failed: %s', $baseName));
            }
        }
    }

    closedir($handle); #탐색한 폴더 닫기
}

$zip->close(); #압축파일 닫기

$file = "pwdtest.zip"; #다운로드 할 때 정해줄 이름
$down = $zipfile; #실제 다운로드할 파일
$filesize = filesize($down);

if(file_exists($down)) {
    header("Content-Type:application/octet-stream");
    header("Content-Disposition:attachment;filename=$file");
    header("Content-Transfer-Encoding:binary");
    header("Content-Length:".filesize($down));
    header("Cache-Control:cache,must-revalidate");
    header("Pragma:no-cache");
    header("Expires:0");
    if(is_file($down)) {
        $fp = fopen($down,"r");
        while(!feof($fp)) {
            $buf = fread($fp,8096);
            $read = strlen($buf);
            print($buf);
            flush();
        }
        fclose($fp);
    }
} else {
    #파일이 존재하지 않을 때 오류 메시지
}

참고자료

PHP: ZipArchive - Manual


반응형