Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 2234
  • Last Modified:

Zip and download file php ajax

Hello,
  I have a an application that display  some file data to the user E.g

[]|filename| size

When the user select one or more files. I would like to post the selected file  information back to the server. Then server then zip the file(s) and send the data to the browser.

How can I do this with an Ajax call?. I have server side script that accept the file data and contruct the zip file. How do I send the zip back to the browser and have it force the user to save or open the file.

Thanks
0
SiemensSEN
Asked:
SiemensSEN
  • 4
  • 3
  • 3
3 Solutions
 
Erdinç Güngör ÇorbacıPHP Development Team LeaderCommented:
Just sending user to the file url like http://www.domain.com/filename.zip should make visitor able to open or download.

What problem do you have when you do this.

PS: Dont send browser to file url through ajax if you do. Send them through the opened page.

If there is problem with multiple files you can use targetting to _blank by creating hidden <a> links for each file and triggering them with javascript.
0
 
Ray PaseurCommented:
This may work for you, however I would add some security checks to it before I released it into the wild.

<?php // RAY_force_download_GET.php
error_reporting(E_ALL);

// EXAMPLE OF USAGE
// <a target="_blank"
//    href="RAY_force_download_GET.php?u=http://www.google.com/intl/en_ALL/images/logo.gif">Google Logo</a>


// REQUIRED FOR USE WITH THE PHP date() FUNCTIONS
date_default_timezone_set('America/New_York');

// THE NAME OF THE FILE TO DOWNLOAD IS IN THE URL
$url = !empty($_GET["u"]) ? $_GET["u"] : NULL;

// USE CASE
if ($url) force_download($url);



// FUNCTION TO FORCE A DOWNLOAD FROM A FILE
function force_download($filename)
{
    // TRY TO GET THE CONTENTS OF THE FILE
    $filedata = @file_get_contents($filename);

    // SUCCESS
    if ($filedata)
    {
        // GET A NAME FOR THE FILE
        $basename = basename($filename);

        // THESE HEADERS ARE USED ON ALL BROWSERS
        header("Content-Type: application-x/force-download");
        header("Content-Disposition: attachment; filename=$basename");
        header("Content-length: " . (string)(strlen($filedata)));
        header("Expires: ".gmdate("D, d M Y H:i:s", mktime(date("H")+2, date("i"), date("s"), date("m"), date("d"), date("Y")))." GMT");
        header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");

        // THIS HEADER MUST BE OMITTED FOR IE 6+
        if (FALSE === strpos($_SERVER["HTTP_USER_AGENT"], 'MSIE '))
        {
            header("Cache-Control: no-cache, must-revalidate");
        }

        // THIS IS THE LAST HEADER
        header("Pragma: no-cache");

        // FLUSH THE HEADERS TO THE BROWSER
        flush();

        // CAPTURE THE FILE IN THE OUTPUT BUFFERS - WILL BE FLUSHED AT SCRIPT END
        ob_start();
        echo $filedata;
    }

    // FAILURE
    else
    {
        die("ERROR: UNABLE TO OPEN $filename");
    }
}

Open in new window

0
 
Erdinç Güngör ÇorbacıPHP Development Team LeaderCommented:
Hi Ray , Very extensible approach i'll add this to my helpers library with some changes , thanks.

But i have a question ; Do this usage loads file completely to our server?
If so, does, passing file completely through php, slows down server or result with a timeout ?
- if the file is big or/and from a slow remote host-

For instance for a mkv file about 500MB, which is on a remote server.
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
Ray PaseurCommented:
Yes, this will pass the entire contents of the file through the server.  Its purpose is to cause a download, instead of the normal action associated with the browser.  If the normal browser action is acceptable (render HTML or images, open a PDF, etc), there would be no need to force a download.
0
 
SiemensSENAuthor Commented:
Thanks,
I will use the download script but call it from my Ajax script

This is what I am trying to do---

I have  a grid where users can select multiple files. When the "Download" button is press , I get all the selected files. Then send it to the server via ajax call . On the server I have a method that get the files and compress them into a zip file. Finally, I would like to render the file to browser The browser should  force the user to save or download the zip file

Thanks erdincgc.

 no issue ... did not know how to do it
0
 
Ray PaseurCommented:
In case you are planning to use zip functions via PHP, you might want to reconsider.  It can be very difficult to get the zip archive right.  If it were my task, I would go in the direction of zipping the files and storing the zipped version, rather than using PHP to create a zip archive on the fly.  Just a thought.... ~Ray
0
 
SiemensSENAuthor Commented:
The problem is the file are already zip . Based on some user selected criteria , the user will be presented with multiple zip files. They can then select one or more. zip files  Then, the application should download the file .

I was planning to get all the zip file (size limit) and combining into one zip archive and then send it to the browser for download

for example , my display is in a grid below. So, the user can select all .

e.g display
<download>
[] file| size
[] f1.gz |1mb
[] f2.gz | 2mb
[] f3.gz |1mb

Ray what would be the best approach
0
 
Ray PaseurCommented:
I don't really know what would happen if you made a zip archive from files that are already zipped.  This code did the trick for me (just as a teaching example) .  You might be able to adapt if for your project.

<?php // RAY_zip_archive.php
error_reporting(E_ALL);
date_default_timezone_set('America/New_York');

// THE URL ARGUMENT IS THE NAME OF THE DIRECTORY TO ZIP
$dir = (!empty($_GET["dir"])) ? $_GET["dir"] : NULL;

// BUT FOR MY TESTS IT IS HARDCODED
$dir = 'RAY_aslimages';

if (!$dir) die("PLEASE PROVIDE dir= IN THE URL");

// A GOOD PATH ON MY SERVER
$path
= getcwd()
. DIRECTORY_SEPARATOR
. $dir
;
if (!is_dir($path)) die("FAIL: NOT VALID PATH $path");

// THIS IS THE LIST OF scandir() RESPONSES THAT WE DO NOT WANT
$unwanted
= array
( '.'
, '..'
, 'teste2.txt'
)
;

// INSTANTIATE THE OBJECT
$zip = new ZipArchive();

// CREATE A DATE-TIME ARCHIVE NAME
$archive
= date('Ymd\THis')
. '_archive_'
. $dir
. '.zip'
;

// TRY TO CREATE THE ARCHIVE
if ($zip->open($archive, ZIPARCHIVE::CREATE)!==TRUE) die("FAIL: ZIP->OPEN <$archive>");

// GET THE LIST OF FILES
if (!$files = scandir($path))   die("FAIL: scandir() $path");
foreach ($files as $file)
{
    // SKIP THE UNWANTED AND ADD THE OTHERS TO THE ARCHIVE
    if ( in_array($file, $unwanted) )                    continue;
    if ( !is_file($path . DIRECTORY_SEPARATOR . $file) ) continue;
    $zip->addFile($path . DIRECTORY_SEPARATOR . $file );
}

if (!$zip->close()) die("FAIL: ZIP->CLOSE");

$fs  = filesize($archive);
$fsn = number_format($fs);


// PREPARE A LINK
$link
= '<a target="_blank" href="'
. $archive
. '">'
. "DOWNLOAD $archive $fsn BYTES"
. '</a>'
;
// echo $link;

// SEND THE ZIP ARCHIVE
header("Content-Type: archive/zip");
header("Content-Disposition: attachment; filename=$dir".".zip");
header("Content-Length: $fs");
readfile($archive);

Open in new window

0
 
Erdinç Güngör ÇorbacıPHP Development Team LeaderCommented:
I don't know the end structure of your site but if you can building grouped zip files and let visitor to choose group rather than each one by one may be a better approach if your options are not so many building every combination first maybe much more better to reduce server loads (while building zip files).

Or let user download each file one by one , most of sites use this method.

But if you are confident about your server you may go straight on. Even In this option you may create combinations in specific formatted filenames such as ;

if file1 file2 and file 3 is checked
make combined file name as file1-file2-file3.zip.
And then if you check file existence before building again.

You may gain some cpu load from the ones built before.
0
 
SiemensSENAuthor Commented:
Thanks .
I used the code provided to  create a php file "download.php".Then call it via ajax..

Here my code

<iframe id="frameDownload"></iframe>
<script>
$.ajax({
             url:"myurl",
             type:"POST",
             datatype:"text",
             data:data,
             success:function(res)
             {    
                 var url = "/download.php?f="+res;
                 $('frameDownload').src=url;
                  window.location = url
             },</script>
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 4
  • 3
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now