Viewed   82 times

I'm trying to force a download of a protected zip file (I don't want people to access it without logging in first.

I have the function created for the login and such , but I'm running into a problem where the downloaded file is corrupting.

Here's the code I have:

$file='../downloads/'.$filename;
header("Content-type: application/zip;n");
header("Content-Transfer-Encoding: Binary");
header("Content-length: ".filesize($file).";n");
header("Content-disposition: attachment; filename="".basename($file).""");
readfile("$file");
exit();

Here's the error: Cannot open file: It does not appear to be a valid archive.

The file downloads fine otherwise, so it must be something I'm doing wrong with the headers.

Any ideas?

 Answers

4

This issue can have several causes. Maybe your file is not found or it can not be read and thus the file’s content is just the PHP error message. Or the HTTP header is already sent. Or you have some additional output that then corrupts your file’s content.

Try to add some error handling into your script like this:

$file='../downloads/'.$filename;
if (headers_sent()) {
    echo 'HTTP header already sent';
} else {
    if (!is_file($file)) {
        header($_SERVER['SERVER_PROTOCOL'].' 404 Not Found');
        echo 'File not found';
    } else if (!is_readable($file)) {
        header($_SERVER['SERVER_PROTOCOL'].' 403 Forbidden');
        echo 'File not readable';
    } else {
        header($_SERVER['SERVER_PROTOCOL'].' 200 OK');
        header("Content-Type: application/zip");
        header("Content-Transfer-Encoding: Binary");
        header("Content-Length: ".filesize($file));
        header("Content-Disposition: attachment; filename="".basename($file).""");
        readfile($file);
        exit;
    }
}
Monday, November 14, 2022
 
2

Instead of using:

$fp = fopen($file, "r");
while (!feof($fp)) {
    echo fread($fp, 65536);
    flush(); // this is essential for large downloads
}
fclose($fp);

Use readfile()

readfile($file);
Friday, September 23, 2022
5

The url is probably a script that may be redirecting you. Use CURL instead

$fh = fopen('file.zip', 'w');
$ch = curl_init()
curl_setopt($ch, CURLOPT_URL, $url); 
curl_setopt($ch, CURLOPT_FILE, $fh); 
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // this will follow redirects
curl_exec($ch);
curl_close($ch);
fclose($fh);
Sunday, November 27, 2022
 
rmk
 
rmk
5

You created a function filedownload() but you never call it, so its body is never executed. You also never define $realfile, the path to the file you want to send.

Call your function:

<?php
  require_once ('./newpub_profile.php');
  $thetitle = $row['title'];
  $thesize = $row['size'];

 function filedownload() { 
    GLOBAL $thesize, $thetitle;
    header("Content-Type: application/msword");
    header("Content-Disposition: attachment; filename=".$thetitle);
    header("Content-Length: ".$thesize);
    header("Content-Transfer-Encoding: binary");
    readfile($realfile);
 }

 filedownload();
?>

Though there doesn't appear to be a reason you have this in a function in the first place:

<?php
  require_once ('./newpub_profile.php');
  $thetitle = $row['title'];
  $thesize = $row['size'];

  header("Content-Type: application/msword");
  header("Content-Disposition: attachment; filename=".$thetitle);
  header("Content-Length: ".$thesize);
  header("Content-Transfer-Encoding: binary");
  readfile($realfile);
?>
Friday, September 30, 2022
1

entry can give you the inputstream of the inner-zip file.

InputStream innerzipstream = zip.getInputStream(entry);

So you can use

new ZipInputStream(innerzipstream);

and ask the ZipInputStream to retrieve the content of the inner-zip-file (in an ordered fashion, you don't have random access because it's a ZipInputStream)

Look at http://download.oracle.com/javase/1.4.2/docs/api/java/util/zip/ZipInputStream.html

Sequential zip access

As ZipInputStream is reading a zip file from an input stream it has to do things in order:

// DO THIS for each entry
ZipEntry e = zipInputStreamObj.getNextEntry();
e.getName // and all data
int size = e.getSize(); // the byte count
while (size > 0) {
   size -= zipInputStreamObj.read(...);
}
zipInputStreamObj.closeEntry();
// DO THIS END

zipInputStreamObj.close();

Note: I don't know if ZipInputStream.getNextEntry() returns null when end of zip file is reached or not. I hope so because I don't know other way to realize when there are no more entries.

Sunday, December 4, 2022
 
jeon
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :