Junius L
Junius L

Reputation: 16132

AJAX/PHP force file download display contents of zip file in the browser

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

Upvotes: 0

Views: 2710

Answers (3)

Junius L
Junius L

Reputation: 16132

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

Upvotes: 1

I wrestled a bear once.
I wrestled a bear once.

Reputation: 23379

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.

Upvotes: 1

qwerty_igor
qwerty_igor

Reputation: 939

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

Upvotes: 1

Related Questions