Jump to content

problem with downlod script - maybe wrong headers?


Bottyz

Recommended Posts

Hi all,

 

I wrote a download script for some protected files a little while back. And on the whole, its works pretty well but occasionally, zip files will not completely download and will end up corrupted. It happens more with bigger files but that i'm guessing is due to the fact it takes longer to download them?

 

I've searched intensively on Google for the past few days and implemented a few new ideas, which hasn't made a difference. Its annoying, in the fact you can try the same file a few times over and it'll download 8 out of 10 times no problem. I even added in the apachesentenv after a recommendation, as the rest of my site is gzip php'd. But that hasn't worked either.

 

Part of the code as follows:

 

apache_setenv('no-gzip', '1');
// if file exists and user access granted:

// define the path to your download folder plus assign the file name
$path .= $filename;

// check that file exists and is readable
if (file_exists($path) && is_readable($path)) {

// get the file size and send the http headers
$size = filesize($path);

        // required for IE, otherwise Content-disposition is ignored
        if(ini_get('zlib.output_compression')) ini_set('zlib.output_compression', 'Off');

//content type
switch(strtolower(substr(strrchr($filename,'.'),1)))
{
        case "pdf": $mime="application/pdf"; break;
        case "mp3": $mime="audio/x-mp3"; break;
        case "zip": $mime="application/zip"; break;
        case "rar": $mime="application/zip"; break;
        case "tar": $mime="application/zip"; break;
        case "sit": $mime="application/zip"; break;
        case "doc": $mime="application/msword"; break;
        case "xls": $mime="application/vnd.ms-excel"; break;
        case "ppt": $mime="application/vnd.ms-powerpoint"; break;
        case "gif": $mime="image/gif"; break;
        case "png": $mime="image/png"; break;
        case "jpeg":$mime="image/jpg"; break;
        case "jpg": $mime="image/jpg"; break;
        default: $mime="application/force-download";
}

header("Cache-Control: public");
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Content-Description: File Transfer");
header("Content-Type: " .$mime);
header("Content-Disposition: attachment; filename=\"{$filename}\"");
header('Content-Transfer-Encoding: binary');
header('Content-Length: ' . filesize($path));
readfile("$path");

if($logging == 1){
	$status = "Granted";
	include('logit.php');
}
exit;
}

 

Live http Headers in Firefox displays the following upon clicking a download:

 

http://www.website.com/filedownload.php?file=12

GET /filedownload.php?file=12 HTTP/1.1
Host: www.website.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12 ( .NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://www.website.com/downloads.php
Cookie: __utma=100661891.2064943237.1286446219.1290502952.1290505322.70; __utmz=100661891.1290502952.69.8.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=lighthouse%20cjpro; __utmc=100661891; __utmb=100661891.43.10.1290505322; PHPSESSID=8aadcc17930b9e146f103f180f30f470

HTTP/1.1 200 OK
Date: Tue, 23 Nov 2010 11:22:13 GMT
Server: Apache/2.2.14 (Unix) mod_ssl/2.2.14 OpenSSL/0.9.8e-fips-rhel5 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635 PHP/5.2.12
X-Powered-By: PHP/5.2.12
Expires: 0
Cache-Control: must-revalidate, post-check=0, pre-check=0
Pragma: public
Content-Description: File Transfer
Content-Disposition: attachment; filename="Version_5_Software.zip"
Content-Transfer-Encoding: binary
Content-Length: 62654423
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: application/zip
----------------------------------------------------------

 

Are my headers wrong? or in the incorrect order? If not, any ideas? I'm a bit stumped!

 

Thanks for taking the time to read my query.

 

 

Link to comment
Share on other sites

any chance your script is timing out before sending the whole file?

 

It did cross my mind, but if thats the case then why does it work most of the time and not some of the time?

 

Currently, It will corrupt with all sizes of zip file (since changes i made). Current code is as above and 8 times out of 10 the zips will download fine. Sometimes the file can say its downloaded instantaneously and you open it to find its corrupted, even when the file is supposed to be 40mb? It always states the correct file size when you click save as.  :shrug:

 

Its as if something interrupts the download.  :confused:

 

Any further help would be appreciated as always! This is getting very frustrating  :wtf: :'(

Link to comment
Share on other sites

Hi all,

 

 

I've implemented a different set of headers now, which seem to work but won't allow users to download more than one file at a time. Is the following a safe way of overcoming the problem?

 

// if file exists and user access granted:
// define the path to your download folder plus assign the file name
$path .= $filename;

// check that file exists and is readable
if (file_exists($path) && is_readable($path)) {
	apache_setenv('no-gzip', '1');
        // required for IE, otherwise Content-disposition is ignored
        if(ini_get('zlib.output_compression')) {
		ini_set('zlib.output_compression', 'Off');
	}
	//content type
	switch(strtolower(substr(strrchr($filename,'.'),1)))
	{
          case "pdf": $mime="application/pdf"; break;
          case "zip": $mime="application/zip"; break;
          case "doc": $mime="application/msword"; break;
          case "xls": $mime="application/vnd.ms-excel"; break;
          case "jpeg":$mime="image/jpg"; break;
          case "jpg": $mime="image/jpg"; break;
	  default: $mime="application/force-download";
	}

	header('Content-Disposition: attachment; filename=' . urlencode($filename));   
	header('Content-Type: application/force-download');
	header('Content-Type: application/octet-stream');
	header('Content-Type: application/download');
	header('Content-Description: File Transfer');            
	header('Content-Length: ' . filesize($path));
	echo file_get_contents($path);
	if($logging == 1){
		$status = "Granted";
		include('logit.php');
	}
	exit;
}

 

 

:-\

Link to comment
Share on other sites

Right ok,

 

after more tweaking and even looking into cURL as a method of correcting the file downloads (and omitting it as i can't figure out how to present a user with a save to.. dialog), i've come up with the following:

 

// if file exists and user access granted:

// Set maximum script execution time in seconds (0 means no limit)
set_time_limit(0);

// define the path to your download folder plus assign the file name
$path .= $filename;

// file size in bytes
$fsize = filesize($path);

// check that file exists and is readable
if (file_exists($path) && is_readable($path)) {
	apache_setenv('no-gzip', '1');
        // required for IE, otherwise Content-disposition is ignored
        if(ini_get('zlib.output_compression')) {
		ini_set('zlib.output_compression', 'Off');
	}
	//content type
	switch(strtolower(substr(strrchr($filename,'.'),1)))
	{
          case "pdf": $mime="application/pdf"; break;
          case "zip": $mime="application/zip"; break;
          case "doc": $mime="application/msword"; break;
          case "xls": $mime="application/vnd.ms-excel"; break;
          case "jpeg":$mime="image/jpg"; break;
          case "jpg": $mime="image/jpg"; break;
	  default: $mime="application/force-download";
	}

	// set headers
	header("Pragma: public");
	header("Expires: 0");
	header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
	header("Cache-Control: public");
	header("Content-Description: File Transfer");
	header("Content-Type: $mime");
	header("Content-Disposition: attachment; filename=\"$filename\"");
	header("Content-Transfer-Encoding: binary");
	header("Content-Length: " . $fsize);

	// download
	$file = @fopen($path,"rb");
	if ($file) {
	  while(!feof($file)) {
	   print(fread($file, 1024*);
	   flush();
	   if (connection_status()!=0) {
	     @fclose($file);
	     die();
	    }
	  }
	  @fclose($file);
	}

	if($logging == 1){
		$status = "Granted";
		include('logit.php');
	}
	exit;
}

 

The above seems to work with all files again now, but will need some constant testing for a little while to see if i get anymore corrupted transfers.

 

If anyone can see any obvious mistakes in the code snippet above, please let me know. Also, can anyone see any issues with cpu usage or similar on the above? Hopefully the code will also help anyone else with similar issues...

 

If i don't get anymore errors, i'll post back and mark as solved. I'm surprised no more of you php wizards have been able to help further? Maybe i posted on a dodgy topic. Thanks for reading my random rantings and thoughts anyways!

 

PS. On another note, anybody have an idea as to how you would allow pausing and resuming of downloads? Or am i looking too much into this? lol!  ;D

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.