开发者

PHP only half of file is downloaded

I have some larger files which I need to share with people and to make it easier for them (and for the fun of developing it) I am developing a small browser-based FTP client. It's nothing more than the standard functions in PHP.

Yesterday I made a question here about how to download AVI files to the client and I found this function to do so:

<?php 

/* Tutorial by AwesomePHP.com -> www.AwesomePHP.com */ 
/* Function: download with resume/speed/stream options */ 

/* 
    Parametrs: downloadFile(File Location, File Name, 
    max speed, is streaming   
    If streaming - movies will show as movies, images as images 
    instead of download prompt 
*/ 
     
function downloadFile($fileLocation,$fileName,$maxSpeed = 100,$doStream =
false){ 
    if (connection_status()!=0) return(false); 
    $extension = strtolower(end(explode('.',$fileName))); 

    /* List of File Types */ 
    $fileTypes['swf'] = 'application/x-shockwave-flash'; 
    $fileTypes['pdf'] = 'application/pdf'; 
    $fileTypes['exe'] = 'application/octet-stream'; 
    $fileTypes['zip'] = 'application/zip'; 
    $fileTypes['doc'] = 'application/msword'; 
    $fileTypes['xls'] = 'application/vnd.ms-excel'; 
    $fileTypes['ppt'] = 'application/vnd.ms-powerpoint'; 
    $fileTypes['gif'] = 'image/gif'; 
    $fileTypes['png'] = 'image/png'; 
    $fileTypes['jpeg'] = 'image/jpg'; 
    $fileTypes['jpg'] = 'image/jpg'; 
    $fileTypes['rar'] = 'application/rar';     
     
    $fileTypes['ra'] = 'audio/x-pn-realaudio'; 
    $fileTypes['ram'] = 'audio/x-pn-realaudio'; 
    $fileTypes['ogg'] = 'audio/x-pn-realaudio'; 
     
    $fileTypes['wav'] = 'video/x-msvideo'; 
    $fileTypes['wmv'] = 'video/x-msvideo'; 
    $fileTypes['avi'] = 'video/x-msvideo'; 
    $fileTypes['asf'] = 'video/x-msvideo'; 
    $fileTypes['divx'] = 'video/x-msvideo'; 

    $fileTypes['mp3'] = 'audio/mpeg'; 
    $fileTypes['mp4'] = 'audio/mpeg'; 
    $fileTypes['mpeg'] = 'video/mpeg'; 
    $fileTypes['mpg'] = 'video/mpeg'; 
    $fileTypes['mpe'] = 'video/mpeg'; 
    $fileTypes['mov'] = 'video/quicktime'; 
    $fileT开发者_如何学编程ypes['swf'] = 'video/quicktime'; 
    $fileTypes['3gp'] = 'video/quicktime'; 
    $fileTypes['m4a'] = 'video/quicktime'; 
    $fileTypes['aac'] = 'video/quicktime'; 
    $fileTypes['m3u'] = 'video/quicktime'; 

    $contentType = $fileTypes[$extension]; 
     
     
    header("Cache-Control: public"); 
    header("Content-Transfer-Encoding: binary\n"); 
    header('Content-Type: $contentType'); 

    $contentDisposition = 'attachment'; 
     
    if($doStream == true){ 
        /* extensions to stream */ 
        $array_listen = array('mp3','m3u','m4a','mid','ogg','ra','ram','wm', 
        'wav','wma','aac','3gp','avi','mov','mp4','mpeg','mpg','swf','wmv','divx','asf'); 
        if(in_array($extension,$array_listen)){  
            $contentDisposition = 'inline'; 
        } 
    } 

    if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) { 
        $fileName= preg_replace('/\./', '%2e', $fileName, substr_count($fileName,
'.') - 1); 
        header("Content-Disposition: $contentDisposition;
filename=\"$fileName\""); 
    } else { 
        header("Content-Disposition: $contentDisposition;
filename=\"$fileName\""); 
    } 
     
    header("Accept-Ranges: bytes");    
    $range = 0; 
    $size = filesize($fileLocation); 
     
    if(isset($_SERVER['HTTP_RANGE'])) { 
        list($a, $range)=explode("=",$_SERVER['HTTP_RANGE']); 
        str_replace($range, "-", $range); 
        $size2=$size-1; 
        $new_length=$size-$range; 
        header("HTTP/1.1 206 Partial Content"); 
        header("Content-Length: $new_length"); 
        header("Content-Range: bytes $range$size2/$size"); 
    } else { 
        $size2=$size-1; 
        header("Content-Range: bytes 0-$size2/$size"); 
        header("Content-Length: ".$size); 
    } 
         
    if ($size == 0 ) { die('Zero byte file! Aborting download');} 
    set_magic_quotes_runtime(0);  
    $fp=fopen("$fileLocation","rb"); 
     
    fseek($fp,$range); 
   
    while(!feof($fp) and (connection_status()==0)) 
    { 
        set_time_limit(0); 
        print(fread($fp,1024*$maxSpeed)); 
        flush(); 
        ob_flush(); 
        sleep(1); 
    } 
    fclose($fp); 
            
    return((connection_status()==0) and !connection_aborted()); 
}  

/* Implementation */ 
downloadFile('fileLocation','fileName.ext',900,false); 

?>

Now my issue is that when downloading large files (about 800 MB) I am only getting half of the file (about 440 MB) and I have no idea why this is. Can anyone tell me what I am doing wrong or does anyone have an idea what I can do different?

As mentioned, I use this function combined with my script below.

    require_once 'func_downloadFile.php';

    // Get filename
    $filename = explode("/", $_GET['file']);
    $filename = $filename[count($filename)-1];

    $file_path = "downloads/" . $filename;

    if(file_exists($file_path)) {
        downloadFile($file_path, $filename, 900, false);
    }
    else {
        echo "File does not exist.";
    }

First the file is downloaded from my NAS onto my webserver and then sent to the client. If I use my script for downloading to the client I am only getting half of the file but if I download the file from my NAS to my webserver, then log into tmy webserver through and FTP client and download the file, I will get the whole file. So the issue is when sending from webserver to client (which is what downloadFile() does)

EDIT: I tried checking if safe_mode was on using if(ini_get('safe_mode')){ which returned false. Therefore I tried adding the two lines below to set the timeout to unlimited but the result is the same.

ini_set('max_execution_time', 0);
set_time_limit(0);


Try changing your timeout settings. The entry is called max_execution_time and you can find it in your php.ini file. The standard is 30 second. (set_time_limit won't work in safe mode)


Is it possible you are hitting the script execution time limit? (Default 30 seconds)

You can edit your function to reset the time limit in the loop...

while(!feof($fp) and (connection_status()==0)) {
    set_time_limit(30); 
    ...
}

You can't set the limit higher without editing php.ini, but putting this in the loop will reset it on each iteration of the loop.

Are there any entries in the httpd error log?


set_time_limit will allow you to adjust the maximum execution time of the script see http://php.net/manual/en/function.set-time-limit.php

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜