Download of .zip file runs a corrupted file php

41,404

Solution 1

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;
    }
}

Solution 2

I bet two beers that a PHP error occurs, and the error message messes up the ZIP file. The requested file probably doesn't exist.

Open the ZIP file with notepad or a similar text editor, and find out what's wrong.

Solution 3

Late answer but maybe useful for users not being able to make force download work.
Add the following at the top of your php script

<?php
apache_setenv('no-gzip', 1);
ini_set('zlib.output_compression', 0);

Solution 4

I had similar problems for large zip files This works for me:

In your php.ini, change to:

  • Upload_max_filesize - 1500 M
  • Max_input_time - 1000
  • Memory_limit - 640M
  • Max_execution_time - 1800
  • Post_max_size - 2000 M

In your php file.

    $filename = "MyFile.zip";           
    $filepath='../downloads/'.$filename;    //your folder file path    
    header($_SERVER['SERVER_PROTOCOL'].' 200 OK');
    header("Content-Type: application/zip");
    header("Content-Transfer-Encoding: Binary");    
    header("Content-Length: ".filesize($filepath)); 
    header("Content-Disposition:attachment;filename=\"".basename($filepath)."\"");


    while (ob_get_level()) 
    {
     ob_end_clean();
     }
    readfile($filepath);   
    exit;
    ob_start ();

Solution 5

Here is the solution create a file with name .htaccess write below line in that SetEnv no-gzip dont-vary

upload the file to your website. If you have the file already there then please make the above change in that

Share:
41,404
Troy
Author by

Troy

Updated on October 17, 2020

Comments

  • Troy
    Troy over 3 years

    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?

  • prodigitalson
    prodigitalson over 14 years
    id agree i bet there is an error in the readfile() like invalid permissions, or it can be found...
  • Troy
    Troy over 14 years
    Awesome Gumbo! That answered it. That was it... I think the sent headers is the reason why it wasn't working.
  • Rajib Sarker
    Rajib Sarker about 4 years
    opening with notepad to see the error message was a life-saver. thanks man! :)
  • Momoro
    Momoro about 4 years
    @Gumbo My file does exist, but for some reason it returns a 'File Not Found'? Any ideas?
  • Ivan Shumakov
    Ivan Shumakov almost 3 years
    It works for me just because of "while" section. Anyway, what it means "while ob_get_level ob_end_clean"?
  • borgomeister
    borgomeister over 2 years
    ob_get_level — Return the nesting level of the output buffering mechanism ob_end_clean — Clean (erase) the output buffer and turn off output buffering
  • Willt42
    Willt42 over 2 years
    This answer gave me the idea that maybe ANY output at all (not just errors) might mess up the Zip file. Turns out my echo statements were messing it up. Removed all echo's and voila it works.
  • LUISAO
    LUISAO about 2 years
    Thank you @Pekka. It has a message inside my file. So, i get the manual PHP and a user marro at cz put --- ob_clean(); flush(); --- before the readfile(). It Works!
  • LUISAO
    LUISAO about 2 years
    Read message from @Pekka. It has a message inside my file. So, i get the manual PHP and a user marro at cz put --- ob_clean(); flush(); --- before the readfile(). It Works!