s

PHP에서 파일다운로드기능 구현하기

· 2023-07-05 (수) 09:29:55 · 3092

대체로 PHP에서 파일을 다운로드하는 기능을 구현하기 위해 아래의 코드처럼 readfile()함수를 사용합니다.

[code]

$file = 'monkey.gif';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}

[/code]

그런데 readfile()함수는 파일크기만큼의 RAM영역을 차지하고 있으며 만일 메모리크기가 모자란다고 해도 오류를 발생시키지 않는 약점이 있습니다.

때문에 파일다운로드가 자주 발생하는 웹에서는 readfile()보다는 일정한 크기만큼씩 파일내용을 출력시키는 안전한 다운로드방식을 사용합니다. 다음의 코드가 바로 이런 점을 고려한 코드입니다.

[code]
64kb 씩 파일내용을 읽어 출력시키는 함수

public function download($path, $buf=64)
{
    $fullpath = $path;
    $name = pathinfo($fullpath)['basename'];

    if(strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) // Browser is Internet Explorer
    {
        $filename = urlencode($name);
        $filename = preg_replace('/\./', '%2e', $filename, substr_count($filename, '.') - 1);
        $filename = basename(str_replace("+", "%20", $filename));
    }
    else $filename = $name;


    if (!is_file($fullpath) or connection_status()!=0) return(false);

    while(ob_get_level()) @ob_end_clean();

    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Pragma: public");
    header("Expires: ".gmdate("D, d M Y H:i:s", mktime(date("H")+2, date("i"), date("s"), date("m"), date("d"), date("Y")))." GMT");
    header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
    header("Content-Type: application/octet-stream");
    header("Content-Length: ".(string)(filesize($fullpath)));
    header("Content-Disposition: inline; filename=\"$filename\""); // Important the quotes \"\" for Firefox
    header("Content-Transfer-Encoding: binary\n");

    if($this->getUseSession() === true) session_write_close();

    if ($file = fopen($fullpath, 'rb'))
    {
        while(!feof($file) and (connection_status()==0))
        {
            set_time_limit(0); // Need if use max_execution_time set with php.ini.
            print(fread($file, 1024*intval($buf)));
            @ob_flush();
            @flush();
        }
        fclose($file);
    }
    return((connection_status()==0) and !connection_aborted());
}

[/code]

 

대용량 파일들을 다운로드 하는데서 위와 같은 코드가 안정적이지만 다운로드 하는 시간이 좀 걸리는 약점도 있습니다. 그것은 한번에 64KB씩(또는 사용자의 지정에 따르는 크기) 쪼각화해서 전송하기 떄문입니다.

도움이 되길 바랍니다.

|
댓글을 작성하시려면 로그인이 필요합니다.

개발자팁

5,403건

개발과 관련된 유용한 정보를 공유하세요. 질문은 QA에서 해주시기 바랍니다.

+
분류 제목 글쓴이 날짜 조회
JavaScript 22-05-26 조회 2,380
기타 22-05-25 조회 2,002
기타 22-05-24 조회 2,216
기타 22-05-22 조회 2,050
웹서버 22-05-17 조회 2,939
PHP 22-05-11 조회 1,977
PHP 22-05-09 조회 2,741
PHP 22-05-06 조회 2,251
JavaScript 22-05-06 조회 2,851
JavaScript 22-04-14 조회 2,882
기타 22-04-07 조회 2,084
JavaScript 22-03-15 조회 2,730
기타 22-03-10 조회 2,080
기타 22-03-08 조회 3,272
웹서버 22-02-28 조회 4,143
JavaScript 22-02-24 조회 2,855
기타 22-02-17 조회 2,375
웹서버 22-02-16 조회 2,458
node.js 22-02-07 조회 2,346
JavaScript 22-01-30 조회 2,178
웹서버 22-01-27 조회 4,098
JavaScript 22-01-20 조회 4,905
JavaScript 22-01-20 조회 2,880
JavaScript 22-01-05 조회 3,304
기타 22-01-05 조회 3,715
OS 22-01-05 조회 2,439
웹서버 21-12-16 조회 2,579
기타 21-12-14 조회 2,375
기타 21-12-13 조회 2,397
기타
[기타]
21-11-29 조회 3,106