SitePoint Sponsor

User Tag List

Results 1 to 12 of 12
  1. #1
    SitePoint Enthusiast
    Join Date
    Aug 2008
    Location
    Taiwan
    Posts
    59
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Transfer a created zip file to the client without storing it on the server?

    I use pclzip.lib.php to compress files on the server into a zip file. For example, the following code will compress "text.txt" in the data folder and whole "images" folder into a zip file named "file.zip".

    Code PHP:
    <?php
     
        include_once('pclzip.lib.php');
     
        $file = new PclZip('file.zip');
     
        $path = $file -> create('data/text.txt,images');
     
        if(!$path) die('Error : ' . $file -> errorInfo(true));
     
    ?>


    But the file.zip will also be stored on the server. How to transfer it to the client instantly without store it on the server?
    Last edited by IanYang; Apr 10, 2009 at 22:07.

  2. #2
    . shoooo... silver trophy logic_earth's Avatar
    Join Date
    Oct 2005
    Location
    CA
    Posts
    9,013
    Mentioned
    8 Post(s)
    Tagged
    0 Thread(s)
    You are going have to store it some where. Having it dynamically created at some defined bitrate while the client's connection is in flux, is more trouble then its worth.
    Logic without the fatal effects.
    All code snippets are licensed under WTFPL.


  3. #3
    SitePoint Enthusiast
    Join Date
    Aug 2008
    Location
    Taiwan
    Posts
    59
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I planned to transfer the created file using javascript at first:

    Code PHP:
    <?php
     
        include_once('pclzip.lib.php');
     
        $file = new PclZip('file.zip');
     
        $path = $file -> create('data/text.txt,images');
     
        if(!$path) die('Error : ' . $file -> errorInfo(true));
     
        echo '<script type="text/javascript">window.location = "http://www.example.com/' . $file . '"</script>';
     
    ?>

    But it may cause some problem. If one client execute this code, a file.zip is created and he is now downloading the file. But if another client execute this code before the previous client finishing his download, then the program will show some error indicate the zip file cannot be overwritten (because a zip file with the same file name is now downloaded by the previous client).
    Last edited by IanYang; Apr 10, 2009 at 21:47.

  4. #4
    SitePoint Wizard
    Join Date
    Mar 2008
    Posts
    1,149
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Save it to a temporary filename. You don't have to redirect the user to the download by the way. You can just send the appropriate headers and then do readfile().

    You may also want to not re-generate the ZIP file if someone recently requested the exact same one.

  5. #5
    SitePoint Enthusiast
    Join Date
    Aug 2008
    Location
    Taiwan
    Posts
    59
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sk89q View Post
    Save it to a temporary filename. You don't have to redirect the user to the download by the way. You can just send the appropriate headers and then do readfile().

    You may also want to not re-generate the ZIP file if someone recently requested the exact same one.
    Thank you! The readfile() function works fine.

    How can I make the server delete the zip file automatically right after all clients finished their downloads?
    Last edited by IanYang; Apr 10, 2009 at 22:05.

  6. #6
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You could just unlink() the file after readfile() completes. If you have multiple users downloading the same file, this could cause problems. But if you just make a distinct filename per users, it should work pretty good.

    You could also periodically delete zip files in that dir that have a fileatime() older than say, 15 minutes or whatever.

  7. #7
    SitePoint Enthusiast
    Join Date
    Aug 2008
    Location
    Taiwan
    Posts
    59
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by crmalibu View Post
    You could just unlink() the file after readfile() completes. If you have multiple users downloading the same file, this could cause problems. But if you just make a distinct filename per users, it should work pretty good.

    You could also periodically delete zip files in that dir that have a fileatime() older than say, 15 minutes or whatever.
    Thank you. It seems make a distinct file name for each user is a better solution. I will handle that later.

    I added unlink($file); after readfile($file); and the zip file was deleted successfully.

    Code PHP:
    <?php
     
        include_once('pclzip.lib.php');
        $file = new PclZip('file.zip');
        $path = $file -> create('data/text.txt,images');
        if(!$path) die('Error : ' . $file -> errorInfo(true));
     
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename=' . $file);
        header('Content-Transfer-Encoding: binary');
        header('Expires: 0');
        header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
        header('Pragma: public');
        header('Content-Length: ' . filesize($file));
        ob_clean();
        flush();
        readfile($file);
        unlink($file);
        exit;
     
    ?>

    But how did the server manage to do this? It deleted the file before I start to download the file. How come I'm still able to download the file?

  8. #8
    SitePoint Addict
    Join Date
    Jul 2008
    Posts
    220
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by IanYang View Post


    But how did the server manage to do this? It deleted the file before I start to download the file. How come I'm still able to download the file?
    well i am not sure, may be readfile($file) will buffer to memory and local copy of hdd been deleted?

    pardon me if i am wrong

  9. #9
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2008
    Posts
    5,757
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    readfile() will return as soon as it writes the data to the output stream. php may buffer its own output stream, and the webserver may buffer as well. You can see flush() and ob_flush() if you want to try to minimize buffering before you unlink.

  10. #10
    SitePoint Enthusiast
    Join Date
    Aug 2008
    Location
    Taiwan
    Posts
    59
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I see. Thank you.

  11. #11
    SitePoint Wizard
    Join Date
    Mar 2008
    Posts
    1,149
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    By the way, you don't really need all those headers.

    Just these three are sufficient (unless you do not want caching under any circumstances and the URLs are not unique):
    PHP Code:
    header('Content-Type: application/octet-stream'); // Should be application/zip, really
    header('Content-Disposition: attachment; filename=' $file);
    header('Content-Length: ' filesize($file)); 
    And you only need the Content-Disposition header if your URL ends in some ugly filename (like download.php?want=images,text).

  12. #12
    SitePoint Enthusiast
    Join Date
    Aug 2008
    Location
    Taiwan
    Posts
    59
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by sk89q View Post
    By the way, you don't really need all those headers.

    Just these three are sufficient (unless you do not want caching under any circumstances and the URLs are not unique):
    PHP Code:
    header('Content-Type: application/octet-stream'); // Should be application/zip, really
    header('Content-Disposition: attachment; filename=' $file);
    header('Content-Length: ' filesize($file)); 
    And you only need the Content-Disposition header if your URL ends in some ugly filename (like download.php?want=images,text).
    Thank you. That makes the code cleaner.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •