0

Hi i'm trying to force download a zip file created from ZipArchive() but the file is not being downloaded instead is displayed/read in the browser.check my code below.

function search(item){
    var search = new XMLHttpRequest();
    search.open("POST","download.php");
    search.onreadystatechange = function(){
        if(search.readyState === 4 && search.status === 200){
            // document.getElementById('tes').innerHTML = search.responseText;
        }
    }
    search.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    search.send("searchItem="+item);
}

download button, calls search function.

<button value="<?php echo "$name"; ?>" onclick="search(this.value)">Download File</button>

PHP code in the download.php file

<?php 
 $name = trim($_POST['searchItem']);
 if(!file_exists("images/$name/$name.zip")){
    //creating a zip file
$zip = new ZipArchive();
$zip_file = "$name".'.zip';
$zip->open("images/$name/".$zip_file, ZipArchive::CREATE);
$files = scandir("images/$name/");
for ($i=2; $i < count($files) ; $i++) { 
$fi = $files[$i];
if(file_exists("images/$name/$fi")){
    $zip->addFile("images/$name/$fi", $fi);
    }
}
$zip->close();

 //force to download the zip
    $file = "images/$name/$zip_file";
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private",false);
    header('Content-type: application/zip');
    header('Content-Disposition: attachment; filename="'.basename($file).'"');
    readfile($file);
    // remove zip file from temp path
    unlink($file);
}
?>
Junius L
  • 15,881
  • 6
  • 52
  • 96
  • 3
    and the large black square ? if i stare at it to long will i go crazy? –  Jun 09 '15 at 02:52
  • You might wanna check this link http://stackoverflow.com/questions/17696516/download-binary-files-with-javascript – qwerty_igor Jun 17 '15 at 22:00
  • It is doable, but better approach might be to generate a link to that file. unless you don't store it as a file but rather a binary string – qwerty_igor Jun 17 '15 at 22:01

3 Answers3

1

Here is what I use to get zip file

 header('Content-Type: application/zip'); // ZIP file
 header('Content-Disposition: attachment; filename="downloadpackage.zip"');
 header('Content-Transfer-Encoding: binary');
 header('Pragma: public');
 header('Content-Description: File Transfer');
 echo($file);

Hope that helps

qwerty_igor
  • 919
  • 8
  • 14
  • Interesting that length wasn't passed, but it worked just fine on a Mac with latest FF, Chrome, Opera, and Safari. Guess one doesn't need to pass data length header anymore. – Volomike Jun 23 '16 at 17:12
  • Yep, I rarely pass content length now. Haven't had issues so far. If anyone knows why, please share. – qwerty_igor Jun 24 '16 at 19:11
1

You cannot download a file with javascript/ajax. You're making this way more difficult than it needs to be. Forget about AJAX and just create a form or an anchor tag that links to the script that generates the ZIP file. Your page will not be redirected so there is no reason to do an XHR.

Javascript, for security reasons, does not have access to your filesystem, therefore you cannot use it to download files. What if every web site you went to was capable of adding files to your computer. That'd be bad. That's why you can't.

I wrestled a bear once.
  • 22,983
  • 19
  • 69
  • 116
1

Since you can't download files using AJAX, The simplest solution is to return the file name to Javascript and use location.href and force file download.

<?php
$name = trim($_POST['searchItem']);
if (!file_exists("images/$name/$name.zip")) {
    //creating a zip file
    $zip = new ZipArchive();
    $zip_file = "$name" . '.zip';
    $zip->open("images/$name/" . $zip_file, ZipArchive::CREATE);
    $files = scandir("images/$name/");
    for ($i = 2; $i < count($files); $i++) {
        $fi = $files[$i];
        if (file_exists("images/$name/$fi")) {
            $zip->addFile("images/$name/$fi", $fi);
        }
    }
    $zip->close();

    //force to download the zip
    $file = "images/$name/$zip_file";
    echo json_encode(['filename' => $file]); // return file name to Javascript
}
?>

Then in Javascript I use location.href to force file download

function search(item){
    var search = new XMLHttpRequest();
    search.open("POST","check.php");
    search.onreadystatechange = function(){
        if(search.readyState === 4 && search.status === 200){
            var data = JSON.parse(search.responseText);
            window.location.href = data.filename; // force file download
        }
    };
    search.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
    search.send("searchItem="+item);
}
Junius L
  • 15,881
  • 6
  • 52
  • 96