Force downloading file not working


#1

Hi, I have been going at this for hours trying to fix this but nothing it working. I'm trying to do a simple domain?id=2 etc and then it checks the user has bought the product and that it exists but when it downloads, it says the size and all but when i go to view it, it says corrupted and that the .zip file is invalid so please can someone tell me what i'm doing wrong.

The way im downloading files is by doing getting the full url and then it downloads it but right now its not working and im not too sure why.

Thanks very much

<?php 

require_once('../system/config-user.php');

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

function get_remote_file_size($url, $readable = true){
   $parsed = parse_url($url);
   $host = $parsed["host"];
   $fp = @fsockopen($host, 80, $errno, $errstr, 20);
   if(!$fp) return false;
   else {
       @fputs($fp, "HEAD $url HTTP/1.1\r\n");
       @fputs($fp, "HOST: $host\r\n");
       @fputs($fp, "Connection: close\r\n\r\n");
       $headers = "";
       while(!@feof($fp))$headers .= @fgets ($fp, 128);
   }
   @fclose ($fp);
   $return = false;
   $arr_headers = explode("\n", $headers);
   foreach($arr_headers as $header) {
			 $s = "Content-Length: ";
       if(substr(strtolower ($header), 0, strlen($s)) == strtolower($s)) {
           $return = trim(substr($header, strlen($s)));
           break;
       }
   }
   
   return $return;
}

function get_ext($name)

{

	$fn = get_basename($name);

	return (strpos($fn, '.') ? strtolower(substr(strrchr($fn, '.'), 1)) : '');

}
function get_basename($name)



{

	return basename(str_replace('\\', '/', $name));

}

function get_filesize_unit($size)



{

	$size = max(0, $size);

	static $u = array('&nbsp;B', 'KB', 'MB', 'GB');

	for ($i=0; $size >= 1024 && $i < 4; $i++)

	{

		$size /= 1024;

	}

	return number_format($size, 1).' '.$u[$i];

}



///////////////////////////////////////////////////////////////////////////////////////////////

function find_mime_type($ext)

{

	static $mime_types = array(


		'application/zip' => array('zip')


	);
	foreach ($mime_types as $mime_type => $exts)
	{
		if (in_array($ext, $exts))
		{
			return $mime_type;
		}
	}
	return 'text/plain';
}
$id = $_GET['id'];
$error = false;
$error = (!$product->is_product($id)?$products->error:$error);
$error =(!$purchases->is_purchased($_SESSION['uid'],$id)?$purchases->error:$error);
if(!$error){
$file = $product->details($id);
$filepath = $file['file'];
$fname=get_basename($filepath);
if (fopen($filepath,r) || (file_exists($filepath)) ){
if (@filesize($filepath)){
$fsize =filesize($filepath);
}
else
{
$fsize =  get_remote_file_size($filepath); 
}
$ext= get_ext($fname);
$ctype= find_mime_type($ext);
header('Content-Type:'. $ctype );
header('Content-Length: ' . $fsize);
header('Content-Disposition: attachment; filename=' . $fname);
$file = fopen($filepath,'r');
fpassthru($file);
}else{
return  'File Doesn\'t Exist';  } // exist fxn....
}
echo $error;
//$downloaded = $purchases->update($_SESSION['uid'],$id,'downloaded','1');
?>

#2

Why are errors suppressed by prefixing functions with @?

If downloading to Windows this may apply:

Note:
On systems which differentiate between binary and text files (i.e. Windows) the file must be opened with 'b' included in fopen() mode parameter.

When I am back on my desktop I will try the script.

Edit:
I would be tempted to try the download examples in the online manual.

http://php.net/manual/en/function.fwrite.php


#3

or if you know a better alternative way to what i'm doing then please say. Thanks in advance


#4

Did you remove @

Did you try the PHP manual examples?


#5

yes i removed the @ and checked the manual but still no luck so do you know any better ways of downloading files?

Thanks


#6

I tried the original script online, removed the @ and numerous other minor changes and it now downloads a zip file with the contents of the index.php file.

Download Demo

Edit:
If the download does not work then please supply a link to the file that you are unabel to download.

Source:

<?php 
declare (strict_types=1); 

ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(-1);

if(0):
  require_once('../system/config-user.php');
endif;  

$forum      = 'https://www.sitepoint.com/community/t/force-downloading-file-not-working/288661';
$id         = $_GET['id'] ?? 1;
$error      = false;
$product    = NULL;
$products   = NULL;
$purchases  = NULL;
$error      = ( $product   && !$product->is_product($id)?$products->error:$error );
$error      = ( $purchases && !$purchases->is_purchased($_SESSION['uid'],$id)?$purchases->error:$error );

if(!$error)
{
  # DEBUG - FORCE FILE NAME
    $fname    = 'DOWNLOAD.zip';  
    $filepath = 'DOWNLOAD.zip';  
    if(0):
      $file     = $product->details($id);
      $filepath = $file['file'];
      $fname    = get_basename($filepath);
    endif;

  if (fopen($filepath, 'r') || (file_exists($filepath)) )
  {
    if (filesize($filepath))
    {
      $fsize =filesize($filepath);
    }else{
      $fsize = get_remote_file_size($filepath); 
    }


    $file = fopen($filepath, 'r');
    if(1):
      $bytesLeft = fpassthru($file);
      $ext    = get_ext($fname);
      $ctype  = find_mime_type($ext);
      if(1):
        header('Content-Type:'    . $ctype );
        header('Content-Length: ' . $fsize);
        header('Content-Disposition: attachment; filename=' . $fname);
      endif;  
    endif;

# header('Content-Type: plain/txt' );
# echo date('l, F lS Y - H:i:s');
# echo '<br><br><br>';

    #DEBUG
    if(1):
      # header('Content-Type: html');
      echo '<br><br><br>';
      echo '<br>gettype($error) ==> ' .gettype($error);      
      echo '<br>$fname ==> ' .$fname;      
      echo '<br>$fsize ==> ' .number_format( (float) $fsize );      
      #echo '<br>$ext   ==> ' .$ext;      
      #echo '<br>$ctype ==> ' .$ctype;      
      echo '<br>$file  ==> ' .$file;
      echo '<br>bytesLeft ==> <br>' .$bytesLeft;
      echo '<br><br> Finished download <br>' . $file;

      $style = 'width:88%; margin:4.2em auto; border:solid 1px #ccc; padding:0.88em;';
      echo '<div style="' . $style .'">';
        highlight_file(__FILE__);
      echo '</div>'; 
    else:  
      $ext    = get_ext($fname);
      $ctype  = find_mime_type($ext);
      if(0):
        header('Content-Type:'    . $ctype );
        header('Content-Length: ' . $fsize);
        header('Content-Disposition: attachment; filename=' . $fname);
      endif;  
    endif;  
  }else{
    return  'File Doesn\'t Exist';  
  } // exist fxn....
}//error
echo '<br><br><br>' .$error .'<br><br><br>';
//$downloaded = $purchases->update($_SESSION['uid'],$id,'downloaded','1');




// ONLY FUNCTIONS BELOW

function get_remote_file_size($url, $readable = true)
{
  $parsed  = parse_url($url);
  $host    = $parsed["host"];
  $fp      = fsockopen($host, 80, $errno, $errstr, 20);
  if(!$fp) 
  {
    return false;
  }else{
   fputs($fp, "HEAD $url HTTP/1.1\r\n");
   fputs($fp, "HOST: $host\r\n");
   fputs($fp, "Connection: close\r\n\r\n");
   $headers = "";
   while(!feof($fp))
   { 
     $headers .= fgets ($fp, 128);
   }  
  }//endif
  fclose ($fp);
  $return      = false;
  $arr_headers = explode("\n", $headers);
  foreach($arr_headers as $header)
  {
    $s = "Content-Length: ";
    if(substr(strtolower ($header), 0, strlen($s)) == strtolower($s))
    {
      $return = trim(substr($header, strlen($s)));
      break;
    }
  }
   
   return $return;
}//


function get_ext($name)
{
  $fn = get_basename($name);

  return (strpos($fn, '.') ? strtolower(substr(strrchr($fn, '.'), 1)) : '');
}

function get_basename($name)
{
  return basename(str_replace('\\', '/', $name));
}

function get_filesize_unit($size)
{
  $size     = max(0, $size);
  static $u = array('&nbsp;B', 'KB', 'MB', 'GB');
  for ($i=0; $size >= 1024 && $i < 4; $i++)
  {
    $size /= 1024;
  }

  return number_format($size, 1).' '.$u[$i];
}


///////////////////////////////////////////////////////////////////////////////////////////////
function find_mime_type($ext)
{
  static $mime_types = array(
    'application/zip' => array('zip')
  );
  foreach ($mime_types as $mime_type => $exts)
  {
    if (in_array($ext, $exts))
    {
      return $mime_type;
    }
  }

  return 'text/plain';
}//

#7

Hi John,

Thanks very much for your help, i implemented your code for the download page and tested it with ?id=2 which the $filepath should get this link http://chewiscripts.x10host.com/newspaper.zip and download the file but i got this error

Warning: fopen(DOWNLOAD.zip): failed to open stream: No such file or directory in download.php on line 32

so im unsure but is it because im using a full link for $file['file']; (http://chewiscripts.x10host.com/newspaper.zip)

Thanks


#8

Could you download the DOWNLOAD.zip file?

Try uploading the above file to the same directory that the script is called and see if the download works.

The script is hardcoded to override the $_GET parameter. Change the 1 to 0 (true to false) and see if the $_GET parameter works.

I am unable to change my script because I am not on my computer.


#9

Thanks for your quick reply

so you want me to change this $id = $GET['id'] ?? 1; to $id = $GET['id'] ?? 0;

for some reason i'm being very stupid and mind-boggled so i don't know if im asking too much but would you be able to configure it so it looks at the $_GET id bit so you know ?id=1 gets the download url for product 1 and ?id=2 gets download url for product 2 etc.

Thanks again very much


#10

also one potential reason maybe why its not working is it bad practice to put ?> at the end of every PHP file that i include/require?


#11

Yes, try Googling for an explanation.


#12

I have revised the following script, tested it thoroughly and the download works OK

Online Demo

Source:

<?php 
declare (strict_types=1); 

ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(-1);

# echo '<pre>'; print_r($_GET); echo '</pre>';
# echo '<pre>'; var_dump($showDetails); echo '</pre>';
# die;

if(0):
  require_once('../system/config-user.php');
endif;  

$forum      = 'https://www.sitepoint.com/community/t/force-downloading-file-not-working/288661';
$id         = $_GET['id'] ?? 1;
$error      = false;
$product    = NULL;
$products   = NULL;
$purchases  = NULL;
$error      = ( $product   && !$product->is_product($id)?$products->error:$error );
$error      = ( $purchases && !$purchases->is_purchased($_SESSION['uid'],$id)?$purchases->error:$error );

$style = 'width:88%; margin:4.2em auto; border:solid 1px #ccc; padding:0.88em;';


if(!$error)
{
  # DEBUG - FORCE FILE NAME
    # $fname    = 'DOWNLOAD.zip';  
    # $filepath = 'DOWNLOAD.zip';  
    $fname    = 'newspaper.zip';  
    $filepath = 'newspaper.zip';  
    $filepath = 'https://www/johns-jokes.com/downloads/sp-i/jack55/'
              . $filepath;
    $fname    = get_basename($filepath);
    if(0):
      $file     = $product->details($id);
      $filepath = $file['file'];
      $fname    = get_basename($filepath);
    endif;

  if (file_exists($fname) )
  {
    if (filesize($fname))
    {
      $fsize =filesize($fname);
    }else{
      $fsize = get_remote_file_size($fname); 
    }

    # 
      $ext      = get_ext($fname);
      $ctype    = find_mime_type($ext);
      $resource = fopen($fname, 'rb');

    #DEBUG
      $showDetails = $_GET['showDetails'] ? TRUE : FALSE;  
      if( $showDetails)
      {  
        # echo '<pre>'; print_r($_GET); echo '</pre>';
        # echo '<pre>'; var_dump($showDetails); echo '</pre>';
        echo '<b style="float:right;"><a href="' .$forum .'"> Forum </a> </b>';
        echo '<hr style="clear:both;">';
        echo '<h1> Download: <a href="??showDetails=FALSE"> ' .$fname .' </a> </h1>';
        echo '<hr style="clear:both;">';
        
        echo '<br>gettype($error) ==> ';
        echo  gettype($error) ? 'TRUE' : '';      
        echo '<br>$fname ==> ' .$fname;      
        echo '<br>$fsize ==> ' .number_format( (float) $fsize );      
        echo '<br>$resource  ==> ' .$resource;
        echo '<br>$ext   ==> ' .$ext;      
        echo '<br>$ctype ==> ' .$ctype;      
        echo '<div style="' . $style .'">';
          highlight_file(__FILE__);
        echo '</div>'; 

      }else{  
        $bytes = fpassthru($resource);
        header('Content-Type:'    .$ctype );
        header('Content-Length: ' .$fsize);
        header('Content-Disposition: attachment; filename=' . $fname);
      }//endif;  

  }else{
    return  '<h1>File Doesn\'t Exist ==> ' .$fname .'</h1>';  
  } // exist fxn....
}//error
echo '<br><br><br>' .$error .'<br><br><br>';
//$downloaded = $purchases->update($_SESSION['uid'],$id,'downloaded','1');




// ONLY FUNCTIONS BELOW

function get_remote_file_size($url, $readable = true)
{
  $parsed  = parse_url($url);
  $host    = $parsed["host"];
  $fp      = fsockopen($host, 80, $errno, $errstr, 20);
  if(!$fp) 
  {
    return false;
  }else{
   fputs($fp, "HEAD $url HTTP/1.1\r\n");
   fputs($fp, "HOST: $host\r\n");
   fputs($fp, "Connection: close\r\n\r\n");
   $headers = "";
   while(!feof($fp))
   { 
     $headers .= fgets ($fp, 128);
   }  
  }//endif
  fclose ($fp);
  $return      = false;
  $arr_headers = explode("\n", $headers);
  foreach($arr_headers as $header)
  {
    $s = "Content-Length: ";
    if(substr(strtolower ($header), 0, strlen($s)) == strtolower($s))
    {
      $return = trim(substr($header, strlen($s)));
      break;
    }
  }
   
   return $return;
}//


function get_ext($name)
{
  $fn = get_basename($name);

  return (strpos($fn, '.') ? strtolower(substr(strrchr($fn, '.'), 1)) : '');
}

function get_basename($name)
{
  return basename(str_replace('\\', '/', $name));
}

function get_filesize_unit($size)
{
  $size     = max(0, $size);
  static $u = array('&nbsp;B', 'KB', 'MB', 'GB');
  for ($i=0; $size >= 1024 && $i < 4; $i++)
  {
    $size /= 1024;
  }

  return number_format($size, 1).' '.$u[$i];
}


///////////////////////////////////////////////////////////////////////////////////////////////
function find_mime_type($ext)
{
  static $mime_types = array(
    'application/zip' => array('zip')
  );
  foreach ($mime_types as $mime_type => $exts)
  {
    if (in_array($ext, $exts))
    {
      return $mime_type;
    }
  }

  return 'text/plain';
}//

#13

thanks for your help and i think it may of just been that the newsletter.zip file was corrupt or something but this code below fixed it but thanks very much anyway John

$id = $_GET['id'];
$error = false;
$error = (!$product->is_product($id)?$products->error:$error);
$error =(!$purchases->is_purchased($_SESSION['uid'],$id)?$purchases->error:$error);
if(!$error) {
$file = $product->details($id);
$file_url = $file['file'];
	//Works
ob_clean();
ob_end_flush();
header('Content-type: application/zip');
header("Content-Transfer-Encoding: Binary"); 
header("Content-disposition: attachment; filename=\"" . basename($file_url) . "\""); 
readfile($file_url);
unlink($file_url);
}
echo $error;

#14

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.