2014-07-14 6 views
0

파일이있는 서버가 있으며 사람들이 파일을 다운로드 할 수 있습니다. 나는 다운로드 보내려면이 코드를 사용 : 내 브라우저 모두를 통해 파일을 다운로드 할 때다운로드 관리자가 PHP 다운로드를 99 % 중단합니다.

<?php 
function dl_file_resumable($file, $is_resume = true) 
{ 
    //First, see if the file exists 
    if (!is_file($file)) { 
     header("HTTP/1.1 400 Invalid Request"); 
     die("<h3>File Not Found</h3>"); 
    } 

    //Gather relevent info about file 
    $size = filesize($file); 
    $fileinfo = pathinfo($file); 

    //workaround for IE filename bug with multiple periods/multiple dots in filename 
    //that adds square brackets to filename - eg. setup.abc.exe becomes setup[1].abc.exe 
    $filename = (isset($_SERVER['HTTP_USER_AGENT']) && strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) ? 
        preg_replace('/\./', '%2e', $fileinfo['basename'], substr_count($fileinfo['basename'], '.') - 1) : 
        $fileinfo['basename']; 

    $file_extension = strtolower($fileinfo['extension']); 

    //This will set the Content-Type to the appropriate setting for the file 
    require 'mineTypes.php'; 

    // Check if the file extension is in $ctype_array & return the value. If not, send default. 
    $ctype = array_key_exists($file_extension, $ctype_array) ? $ctype_array[$file_extension] : 'application/force-download'; 

    $is_resume = ($is_resume && isset($_SERVER['HTTP_RANGE'])); 

    //check if http_range is sent by browser (or download manager) 
    if($is_resume) 
    { 
     $arr = explode('=', $_SERVER['HTTP_RANGE'], 2); 
     if(isset($arr[1])) 
      list($size_unit, $range_orig) = $arr; 
     else list($size_unit) = $arr; 

     if ($size_unit == 'bytes') 
     { 
      //multiple ranges could be specified at the same time, but for simplicity only serve the first range 
      //http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt 
      $arr3 = explode(',', $range_orig, 2); 
      if(isset($arr3[1])) 
       list($range, $extra_ranges) = $arr3; 
      else 
       list($range) = $arr3; 
     } 
     else 
     { 
      $range = ''; 
     } 
    } 
    else 
    { 
     $range = ''; 
    } 

    //figure out download piece from range (if set) 
    $arr2 = explode('-', $range, 2); 
    if(isset($arr2[1])) 
     list($seek_start, $seek_end) = $arr2; 
    else 
     list($seek_start) = $arr2; 

    //set start and end based on range (if set), else set defaults 
    //also check for invalid ranges. 
    $seek_end = (empty($seek_end)) ? ($size - 1) : min(abs(intval($seek_end)),($size - 1)); 
    $seek_start = (empty($seek_start) || $seek_end < abs(intval($seek_start))) ? 0 : max(abs(intval($seek_start)),0); 

    //add headers if resumable 
    if ($is_resume) 
    { 
     //Only send partial content header if downloading a piece of the file (IE workaround) 
     if ($seek_start > 0 || $seek_end < ($size - 1)) 
     { 
      header('HTTP/1.1 206 Partial Content'); 
     } 

     header('Accept-Ranges: bytes'); 
     header('Content-Range: bytes '.$seek_start.'-'.$seek_end.'/'.$size); 
    } 

    header('Content-Type: ' . $ctype); 
    header('Content-Length: '.($seek_end - $seek_start + 1)); 
    header('Content-Disposition: attachment; filename="' . $filename . '"'); 
    header('Accept-Ranges: bytes'); 

    //reset time limit for big files 
    set_time_limit(0); 

    //open the file 
    $fp = fopen($file, 'rb'); 

    //seek to start of missing part 
    fseek($fp, $seek_start); 

    //start buffered download 
    $bytes = 0; 
    while(!feof($fp)) 
    { 
     print(fread($fp, 1024*8)); 
     flush(); 

     $bytes = $bytes + 1024 * 8; 

     ob_flush();   
    } 

    fclose($fp); 
    exit; 
} 

하는 것은 괜찮지 만, 내가 (IDM 같은) 다운로드 관리자를 통해 다운로드 할 때 - 다운로드가 99 %에서 멈 춥니 다.

무엇이 잘못 되었나요?

+0

만약 있기 때문에, flush 에드하지 않습니다, 그것은 클라이언트 양면 문제입니다. 다른 다운로드 관리자를 사용해보십시오. 사용중인 관리자와 문제가있을 수 있습니다. –

+0

@DaveChen 다른 사람들에게도 마찬가지입니다. – HtmHell

+1

나는이 문제에 대해 디버깅을해야 할 것 같습니다. 커맨드 라인에서'wget'을 시도하면 요청으로 범위 헤더를 보낼 수 있어야합니다. 모든 전체 청크가 정상적으로 작동 할 것으로 기대하지만, 마지막 (불완전한) 항목은 어떤 식 으로든 손상됩니다. 해당 부분의 응답 헤더에있는 내용을 확인하십시오. – halfer

답변

0

ob_flush을 먼저 입력하고 flush을 입력해야합니다.

ob_flush 플러시 출력 버퍼 당신은 호출자에 PHP 스크립트 자체의 출력 버퍼 ob_start

flush 홍조와 같은 기능을 만들었습니다.

당신의 마지막 ob_flush는 PHP 스크립트 버퍼에 더 많은 물건을두고 있지만,이 다운로드 관리자에 바로 실패하면 exit;