Create a zip file and download it

136,433

Solution 1

Add Content-length header describing size of zip file in bytes.

header("Content-type: application/zip"); 
header("Content-Disposition: attachment; filename=$archive_file_name");
header("Content-length: " . filesize($archive_file_name));
header("Pragma: no-cache"); 
header("Expires: 0"); 
readfile("$archive_file_name");

Also make sure that there is absolutely no white space before <? and after ?>. I see a space here:

 <?php
$file_names = array('iMUST Operating Manual V1.3a.pdf','iMUST Product Information Sheet.pdf');

Solution 2

$zip = new ZipArchive;
$tmp_file = 'assets/myzip.zip';
    if ($zip->open($tmp_file,  ZipArchive::CREATE)) {
        $zip->addFile('folder/bootstrap.js', 'bootstrap.js');
        $zip->addFile('folder/bootstrap.min.js', 'bootstrap.min.js');
        $zip->close();
        echo 'Archive created!';
        header('Content-disposition: attachment; filename=files.zip');
        header('Content-type: application/zip');
        readfile($tmp_file);
   } else {
       echo 'Failed!';
   }

Solution 3

// http headers for zip downloads
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: application/octet-stream");
header("Content-Disposition: attachment; filename=\"".$filename."\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filepath.$filename));
ob_end_flush();
@readfile($filepath.$filename);

I found this soludtion here and it work for me

Solution 4

One of the error could be that the file is not read as 'archive' format. check out ZipArchive not opening file - Error Code: 19. Open the downloaded file in text editor, if you have any html tags or debug statements at the starting, clear the buffer before reading the file.

ob_clean();
flush();
readfile("$archive_file_name");

Solution 5

I just ran into this problem. For me the issue was with:

readfile("$archive_file_name");

It was resulting in a out of memory error.

Allowed memory size of 134217728 bytes exhausted (tried to allocate 292982784 bytes)

I was able to correct the problem by replacing readfile() with the following:

    $handle = fopen($zipPath, "rb");
    while (!feof($handle)){
        echo fread($handle, 8192);
    }
    fclose($handle);

Not sure if this is your same issue or not seeing that your file is only 1.2 MB. Maybe this will help someone else with a similar problem.

Share:
136,433
Harshal Mahajan
Author by

Harshal Mahajan

The Developer...!!

Updated on February 12, 2020

Comments

  • Harshal Mahajan
    Harshal Mahajan over 4 years

    I am trying to download a 2 files by creating the zip file on local-server.the file is downloaded in zip format but when i try to extract it.it gives error: End-of-central-directory signature not found. Either this file is not a zip file, or it constitutes one disk of a multi-part archive. In the latter case the central directory and zip file comment will be found on the last disk(s) of this archive.

    the following code i am using for this:

     <?php
    $file_names = array('iMUST Operating Manual V1.3a.pdf','iMUST Product Information Sheet.pdf');
    
    //Archive name
    $archive_file_name=$name.'iMUST_Products.zip';
    
    //Download Files path
    $file_path=$_SERVER['DOCUMENT_ROOT'].'/Harshal/files/';
    
    
    zipFilesAndDownload($file_names,$archive_file_name,$file_path);
    
    function zipFilesAndDownload($file_names,$archive_file_name,$file_path)
    {
            //echo $file_path;die;
        $zip = new ZipArchive();
        //create the file and throw the error if unsuccessful
        if ($zip->open($archive_file_name, ZIPARCHIVE::CREATE )!==TRUE) {
            exit("cannot open <$archive_file_name>\n");
        }
        //add each files of $file_name array to archive
        foreach($file_names as $files)
        {
            $zip->addFile($file_path.$files,$files);
            //echo $file_path.$files,$files."
    
        }
        $zip->close();
        //then send the headers to force download the zip file
        header("Content-type: application/zip"); 
        header("Content-Disposition: attachment; filename=$archive_file_name"); 
        header("Pragma: no-cache"); 
        header("Expires: 0"); 
        readfile("$archive_file_name");
        exit;
    }
    
    
    
    
    ?>
    

    i checked the values of all variables which are passing into the function,all are fine.so please look this.Thanks in advance.

  • Barmar
    Barmar over 11 years
    Content-length shouldn't be necessary, the server should automatically use chunked encoding.
  • Harshal Mahajan
    Harshal Mahajan over 11 years
    @kuba, not working..!!and there is no space in my opening and closing tags.
  • Kuba Wyrostek
    Kuba Wyrostek over 11 years
    Can you compare ZIP files on server-side and client-side? Are they identical?
  • Harshal Mahajan
    Harshal Mahajan over 11 years
    yes ,on server side the length of zip file is 226 bytes,and on client side its 1.2 mb.if there is some matter of size than plz give me the exact code for the size of content-length
  • Kuba Wyrostek
    Kuba Wyrostek over 11 years
    server side 226 bytes and client 1.2mb? not the other way round??
  • Harshal Mahajan
    Harshal Mahajan over 11 years
    i just check on local by compressing the files,and it gives size of 1.2 mb,but the file i am getting from server after download it gives the size of 226 bytes.
  • Kuba Wyrostek
    Kuba Wyrostek over 11 years
    OK, please try with Content-length. I provided an example.
  • Harshal Mahajan
    Harshal Mahajan over 11 years
    so now it gives the zip file of length 420 bytes,but still giving same error.
  • Harshal Mahajan
    Harshal Mahajan over 11 years
    Thanks for answer iserni, by putting your code i am getting this error: Fatal error: Could not add /opt/lampp/htdocs/Harshal/files/iMUST Operating Manual V1.3a.pdf as iMUST Operating Manual V1.3a.pdf from script in /opt/lampp/htdocs/Harshal in /opt/lampp/htdocs/Harshal/ex_sub.php on line 25
  • Kuba Wyrostek
    Kuba Wyrostek over 11 years
    OK, it seems to me, that ZIP file isn't completely written to disk before accessed with readfile(). Please add, for the sake of testing only, sleep(5); before readfile("$archive_file_name");.
  • LSerni
    LSerni over 11 years
    I have modified the code to try to better track the error. Looks like a file naming problem, path problem, or permission error.
  • LSerni
    LSerni over 11 years
    @KubaWyrostek, that is very unlikely: $zip functions are disk synchronous, there is no concurrent process performing addFile.
  • Kuba Wyrostek
    Kuba Wyrostek over 11 years
    I am just trying to help. It doesn't cost much to check sleep(). :]
  • Harshal Mahajan
    Harshal Mahajan over 11 years
    now its giving: Fatal error: The input file /opt/lampp/htdocs/Harshal/files/iMUST Operating Manual V1.3a.pdf does not exist in /opt/lampp/htdocs/Harshal/ex_sub.php on line 27
  • Harshal Mahajan
    Harshal Mahajan over 11 years
    i am sure there is a files ,but wondered why this error comes
  • LSerni
    LSerni over 11 years
    Check the contents of the /opt/lampp/htdocs/Harshal/files/ directory (and the permissions on Harshal and Harshal/files too). The file may be there, but PHP believes otherwise.
  • Harshal Mahajan
    Harshal Mahajan over 11 years
    i already given the permission to Harshal/files.but the same error occurs.
  • Harshal Mahajan
    Harshal Mahajan over 11 years
    @kuba ,still giving same size of files.
  • Kuba Wyrostek
    Kuba Wyrostek over 11 years
    sorry, I'm out of hints then... maybe consider using different zip handling library.
  • sdailey
    sdailey over 11 years
    So, the code needs some basic syntax revisions: header("Content-Disposition: attachment; filename=$archive_file_name"); needs to be header("Content-Disposition: attachment; filename=".$archive_file_name); and readfile("$archive_file_name"); needs to be readfile($archive_file_name);
  • Kuba Wyrostek
    Kuba Wyrostek over 11 years
    No it does not. Please consult php.net/manual/en/language.types.string.php Variables are substituted in strings and I didn't want to change original code (not to confuse OP).
  • Jesus Erwin Suarez
    Jesus Erwin Suarez almost 4 years
    Thanks a lot! and this works for me, because I have missing the exact path for the temp file. and my error was this ErrorException-ZipArchive::close(): Failure to create temporary file: Permission denied
  • Beda Schmid
    Beda Schmid almost 3 years
    The solution still is the correct approach, however I suggest using single apostrophes instead of double, it makes it easier to read.
  • Sanjun Dev
    Sanjun Dev almost 3 years
    That's right, I think most of the common reasons for getting unsupported file format errors.