2013-02-02 5 views
3

PHP 스크립트를 통해 URL에서 내 사용자에게 다운로드를 제공하고 있습니다. readfile()을 사용할 때 내 연결이 지원할 수있는 최대 다운로드 속도 (약 2.5MB/초)를 얻을 수 있지만 fopen, fread, fclose 경로를 사용하면 다운로드 속도가 매우 느리고 (약 1-2KB/초) 느려집니다.readfile보다 다운로드 속도가 훨씬 더 빠름

여기 내 코드입니다 :

header('Content-Description: File Transfer'); 
header('Content-Type: application/octet-stream'); 
header('Content-Disposition: attachment; filename=' . $filename); 
header('Content-Transfer-Encoding: binary'); 
header('Expires: 0'); 
header('Cache-Control: must-revalidate'); 
header('Pragma: public'); 
header('Content-Length: ' . $filesize); 
ob_clean(); 
flush(); 

$file = fopen($url, 'rb'); 

while(!feof($file)) { 
    echo fread($file, 2014); 
} 

과 ReadFile을 코드는 단순히 readfile($link);입니다.

가 난 그냥 사용자가 (난 단지 너무 많은 데이터를 읽어 fread로 할 수있는) 속도를 다운로드 제한 할 일이 있기 때문에 두 가지 이유의 readfile() 기능을 사용할 수 없습니다와 나는 또한 얼마나 추적 할 사용자가 다운로드 중입니다 (이 작업은 readfile()으로 수행 할 수 있지만 부분 다운로드는 계산하지 않음).

왜 이런 일이 일어날 지 또는 어떻게 해결할 수 있는지 아는 사람이 있습니까? 지금까지 내가 알고있는 한 readfile()fopen, fread and fclose에 대한 래퍼 일 뿐이므로 잘못된 결과가 나지 않습니다.

편집 :이 경우 cURL과 함께 종료되었습니다.

사용 stream_context_create()
$curl = curl_init(); 
$options = array(
    CURLOPT_URL => $rdLink, 
    CURLOPT_FAILONERROR => true, 
    CURLOPT_BINARYTRANSFER => true, 
    CURLOPT_RETURNTRANSFER => true, 
    CURLOPT_WRITEFUNCTION => 'readResponse' 
); 
curl_setopt_array($curl, $options); 

if(!curl_exec($curl)) { 
    header('Location: http://whatever.com'); 
    exit; 
} 
curl_close($curl); 

function readResponse($ch, $data) { 
    $length = mb_strlen($data, '8bit'); 

    echo $data; 

    return $length; 
} 
+0

출력 버퍼링이 필요합니까? Try'ob_end_flush();' – Boann

+0

확실치 않지만, 다른 곳에서이 코드를 얻었고 출력 버퍼링이있었습니다. 어디서'ob_end_flush();'를 써야합니까? –

+0

글쓰기를 시작하기 전에 아무 데나 놓으십시오. – Boann

답변

2

stream_get_contents()

$context = stream_context_create(); 
$file = fopen($url, 'rb', FALSE, $context); 
while(!feof($file)) 
{ 
    //usleep(1000000); 
    echo stream_get_contents($file, 2014); 
} 

또한 파일 읽기 길이가 더 큰 만들기 및 실행을 느리게하는 usleep()에 넣어 시도 할 수 있습니다. 어쨌든 최신 버전의 PHP에서는 스트림 함수가 fread보다 권장되는 것 같습니다. fread() 또는 stream_get_contents() 앞에 @를 붙이면 적어도 제작시 오류를 억제 할 수 있습니다. 그것이 없으면, 그리고 작은 사고로, 당신은 파일이 손상되었습니다.

+1

이것은 추측입니까 아니면 더 빨라야 할 이유가 있습니까? 대안의 벤치 마크를보고 싶습니다. –

+0

약간의 설명이 필요합니다. stream_get_contents가 더 빠르다면, 왜 fread는 stream_get_contents가하는 일을하지 않습니까? – Boann

+1

이것은 stream_get_contents()가 시간 초과되지 않고 서버의 조건을 기반으로 알고있는 것을 처리한다는 것을 기반으로합니다. 방금 읽은 길이가없는 큰 파일을 각각 시도해 보았습니다. fread가 내부 서버 오류가 발생하여 시간 초과되었습니다. 그리고 stream_get_contents가 작동했습니다. 그러나 2014 년의 읽기 길이는 모두 동일한 실행 시간을 평균으로 계산했습니다. 다른 사람들과 의견을 나누고 싶었지만 '의견 추가'버튼을 클릭하지 않았습니다. 귀하의 회신이 처음 나타난 후에,이 블록에 대해서만 나타났습니다. –

0

PHP 또는 Apache 어딘가에 버퍼링 (또는 속도 제한이있을 수 있음) 될 수 있습니다. 변경 시도 :

while(!feof($file)) { 
    echo fread($file, 2014); 
} 

에 (. 그들은 빈 버퍼에 대해 불평 할 수 있기 때문에 @ 접두사가)

while(!feof($file)) { 
    $s=fread($file, 2014); 
    if($s===false)break; //Crude 
    echo $s; 
    @ob_flush();@flush(); 
} 

mr.freshwater 말했듯이, 당신은 오류 검사를해야한다고 fread 전화를 걸면 위의 내용이 기본으로 추가되었습니다.

0

이유는 2014입니다. OS는 4096 바이트의 데이터 부분을 매우 빠르게 얻습니다. 그러나 2014 년을 작성하면 OS는 파일에서 1 바이트 씩 데이터를 읽으려고 시도합니다. 그래서 오랜 시간이 걸립니다. 변경 2014 to 4096

관련 문제