s

PHP에서 다운로드로직을 구현할때 서버부하문제를 고려한 방법

· 2023-08-31 (목) 20:17:54 · 2091
PHP에서 파일을 웹브라우저에 보내는 방법은 readfile()함수를 사용하는것이 일반적입니다.
[code]

<?php
$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 메모리에 저장되기때문에 다운로드요청이 많아지거나 파일용량이 큰 경우 RAM 부하가 발생하는 문제가 있습니다.

이 문제를 다음과 같은 방법으로 해결할수 있습니다.

[code]

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]
위와 같이 하면 메모리영역은 $buf크기만큼만 점유하면서 웹브라우저에 전송되게 됩니다.

물론 속도가 뜬 결함이 있을수 있으나 용량이 큰 파일들을 다운로드 할때에는 위와 같은 방법이 서버부하를 줄이면서도 안전하다고 생각합니다.

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

개발자팁

5,403건

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

+
분류 제목 글쓴이 날짜 조회
23-04-08 조회 2,618
23-03-31 조회 2,255
23-03-29 조회 2,635
23-03-28 조회 2,029
23-03-27 조회 2,744
JavaScript 23-02-22 조회 3,264
23-02-21 조회 2,483
23-03-10 조회 4,126
23-09-02 조회 2,387
기타 23-08-14 조회 1,593
JavaScript 23-09-04 조회 1,988
node.js 23-09-02 조회 1,603
JavaScript 23-09-01 조회 4,528
PHP 23-08-31 조회 2,092
node.js 23-08-29 조회 1,569
node.js 23-08-28 조회 2,117
PHP 23-08-27 조회 2,735
MySQL 23-08-26 조회 3,151
PHP 23-08-25 조회 3,177
JavaScript 23-08-24 조회 3,756
기타 23-08-23 조회 4,002
기타 23-08-22 조회 1,485
node.js 23-08-21 조회 2,513
JavaScript 23-08-20 조회 2,401
node.js 23-08-19 조회 3,604
node.js 23-08-18 조회 4,620
node.js 23-08-17 조회 3,385
PHP 23-08-16 조회 4,905
node.js 23-08-15 조회 3,531
PHP 23-08-14 조회 4,310