Re: Timeout while waiting for a server->client transfer to start (large files)
| From: | szalinski | Date: | Sun, 03 Feb 2008 16:40:35 +0000 |
| Subject: | Re: Timeout while waiting for a server->client transfer to start (large files) | ||
| References: | 1 2 3 4 | Groups: | php.general |
| Request: | Send a blank email to php-general+get-268594@lists.php.net to get a copy of this message | ||
Thanks
I have already another post dealing with this issue. (check newsgroup for Server to client file transfer always corrupt).
I had figured out the problem that was corrupting the file, it is the response headers that are being added to the file when it is downloaded, and i don't know how to trim them. I am using a different trim method i 'borrowed' from another script (where it seems to work perfectly!), and I just can't understand why it won't work for me, unless as u say, there are other errors being output, but I have looked at the text file and I don't see anything other than the headers there. When I use the trim script to remove them, it also seems to remove part of the start and end of the text file.
I think the most annoying aspect of whole thing is why it is so difficult to find a solution to this problem, i'm sure other people must have come across this problem?
thanks again :)
On Sun, 03 Feb 2008 16:28:34 -0000, Richard Lynch <ceo@l-i-e.com> wrote:
You can use filesize() to get the file size... http://php.net/filesize If that's not going to work because you are stripping out part of the file, or something, Use fgets to get the header info, and then use fseek to reset the file pointer to the beginning: http://php.net/fseek <?php fseek($file, 0);?> You can then read as much or as little as you like with fread. As far as the corrupt files go, compare what you got with the download and the original in a text editor or a hex editor to see what happened. You might have some PHP warnings or notices at the front of the file, or at the end, messing the file contents up. On Thu, January 31, 2008 12:11 pm, szalinski wrote:On Thu, 31 Jan 2008 00:02:55 -0000, Richard Lynch <ceo@l-i-e.com> wrote: <snip>
Hello Richard Well, thank you for pointing that out to me! I was actually trying to read it into RAM, but that was a silly mistake. But now I have the problem that, even though you are correct, the problem seems to still remain, in the sense that I actually *need* to read the start of the file just to get the header info (so i can retrieve the Content-Length, and the filename). Since I tried your method above, I thought I had got the script to finally work - which it seemed to - but every file I download with it is corrupt. I tried downloading a WinRAR file, and I get 'unexpected end of archive'. :( I know for a fact that the archive itself is NOT corrupt, because I tried it with various different files and all of them ended up corrupt! I found some info on the net about fread() and fgets(), and it seems that fgets() only reads one line of data up to 1024 bytes, or in my case, 64 bytes. This is what I want to happen, because I need the 'reading' to abort/break when I have read the required info from the header...I wish (and hope!) there was an easier way to get this info other than searching for it. :| Now I am truly vexed because the files are all corrupt when downloaded, because I can't see anything wrong with the code. I have added a few comments, so you can see what I think is the problematic area. By the way, many thanks for your enthusiastic help so far! - I hope you don't take this email to mean I will be mailing you frequently, believe me I know you must be busy, and I only mailed you as a last resort! Thanks again! <?php //ob_start(); //ob_end_flush(); //ob_implicit_flush(TRUE); $rslogin = ''; $rspass = ''; $link = addslashes(trim($_POST['url'])); function cut_str($str, $left, $right) { $str = substr(stristr($str, $left), strlen($left)); $leftLen = strlen(stristr($str, $right)); $leftLen = $leftLen ? -($leftLen) : strlen($str); $str = substr($str, 0, $leftLen); return $str; } // Get the full premium link, and store it in $full_link after the redirect. *Surely* there is an easier way to get redirections? if(strlen($link)>0) { $url = @parse_url($link); $fp = @fsockopen($url['host'], 80, $errno, $errstr); if (!$fp){ $errormsg = "Error: <b>$errstr</b>, please try againlater.";echo $errormsg; exit; }$vars = "dl.start=PREMIUM&uri={$url['path']}&directstart=1"; $out = "POST {$url['path']} HTTP/1.1\r\n"; $out .= "Host: {$url['host']}\r\n"; $out .= "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n"; $out .= "Authorization: Basic ".base64_encode("{$rslogin}:{$rspass}")."\r\n"; $out .= "Content-Type: application/x-www-form-urlencoded\r\n"; $out .= "Content-Length: ".strlen($vars)."\r\n"; $out .= "Connection: Close\r\n\r\n"; fwrite($fp, $out); fwrite($fp, $out.$vars); unset($string); while (!feof($fp)) { $string.= fgets($fp, 64); } //Tell us what data is returned //print($string); @fclose($fp); if (stristr($string, "Location:")) { $redirect = trim(cut_str($string, "Location:", "\n")); $full_link = $redirect; } //print($string); //print("<html><body><h1>".$full_link."</h1>"); if ($full_link) { // Get info about the file we want to download: $furl = parse_url($full_link);$fvars ="dl.start=PREMIUM&uri={$furl['path']}&directstart=1";$head = "Host: {$furl['host']}\r\n"; $head .= "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0;Windows NT 5.1)\r\n";$head .= "Authorization: Basic".base64_encode("{$rslogin}:{$rspass}")."\r\n";$head .= "Content-Type:application/x-www-form-urlencoded\r\n";$head .= "Content-Length: ".strlen($fvars)."\r\n"; $head .= "Connection: close\r\n\r\n"; $fp = @fsockopen($furl['host'], 80, $errno, $errstr); if (!$fp) { echo "The script says <b>$errstr</b>, please try againlater.";exit; } fwrite($fp, "POST {$furl['path']} HTTP/1.1\r\n"); fwrite($fp, $head.$fvars); while (!feof($fp)) {//Keep reading the info until we get the filename and size from the returned Header - is there no easy way //of doing this? I also don't like the way I have to 'find' the redirected link (above).??$tmp .= fgets($fp, 64);$d = explode("\r\n\r\n", $tmp); // I tried changing this to if ($d), { etc.., (instead of $d[1]) and the download of the rar file *wasn't* corrupt, it just had a filetype of x-rar-compressed instead of //apppication/octet-stream, and the filesize was 'unknown' - now this is just confusing me...! :( So i think (and guess) the problem of the file corruption is here, //because it must add some data to the filestream which corrupts it. Darn. if($d[1]){ preg_match("#filename=(.+?)\n#", $tmp, $fname); preg_match("#Content-Length: (.+?)\n#", $tmp,$fsize);$h['filename'] = $fname[1] != "" ? $fname[1] :basename($furl['path']);$h['fsize'] = $fsize[1];break;}}@fclose($fp);//print($tmp); $filename = $h['filename'];$fsize = $h['fsize'];//Now automatically download the file:@header("Cache-Control:"); @header("Cache-Control: public"); @header("Content-Type: application/octet-stream"); @header("Content-Disposition: attachment;filename=".$filename);@header("Accept-Ranges: bytes"); if(isset($_SERVER['HTTP_RANGE'])) { list($a, $range)=explode("=",$_SERVER['HTTP_RANGE']); $range = str_replace("-", "", $range); $new_length = $fsize - $range; @header("HTTP/1.1 206 Partial Content"); @header("Content-Length: $new_length"); } else { @header("Content-Length: ".$fsize); } $fvars ="dl.start=PREMIUM&uri={$furl['path']}&directstart=1";$head = "Host: {$furl['host']}\r\n"; $head .= "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0;Windows NT 5.1)\r\n";$head .= "Authorization: Basic".base64_encode("{$rslogin}:{$rspass}")."\r\n";$head .= "Content-Type:application/x-www-form-urlencoded\r\n";if($range != "") $head .= "Range: bytes={$range}-\r\n"; $head .= "Content-Length: ".strlen($fvars)."\r\n"; $head .= "Connection: close\r\n\r\n"; $fp = @fsockopen($furl['host'], 80, $errno, $errstr); if (!$fp) { echo "<span style='color:#688000;background-color:#BBDB54; font-size : 10pt; text-decoration: none; font-family: Trebuchet MS;'>The script says <b>$errstr</b>, please try again later.</span>";exit; } @stream_set_timeout($fp, 300); fwrite($fp, "POST {$furl['path']} HTTP/1.1\r\n"); fwrite($fp, $head.$fvars); fflush($fp); while (!feof($fp)) { echo fread($fp, 2048); //ob_flush(); //php.net suggestion }//These were here originally, but I don't even know if I am supposed to have them here.// flush(); // ob_flush; @fclose($fp); exit;} } else {$data = "<form method=\"post\">\n"; $data .= "<input type=\"text\" id=\"url\"style=\"text-align:center\" name=\"url\" size=\"60\" onfocus=\"if(this.value=='Enter rapidshare.com URL here'){this.value=''}\">\n";$data .= "<br><input type=\"submit\"value=\"Download\"></form>";echo $data;} ?>