Manipulate an Archive in memory with PHP (without creating a temporary file on disk)

后端 未结 5 1041
太阳男子
太阳男子 2020-11-27 05:06

I am trying to generate an archive on-the-fly in PHP and send it to the user immediately (without saving it). I figured that there would be no need to create a file on disk

相关标签:
5条回答
  • 2020-11-27 05:25

    I had the same problem but finally found a somewhat obscure solution and decided to share it here.

    I came accross the great zip.lib.php/unzip.lib.php scripts which come with phpmyadmin and are located in the "libraries" directory.

    Using zip.lib.php worked as a charm for me:

    require_once(LIBS_DIR . 'zip.lib.php');
    
    ... 
    
    //create the zip
    $zip = new zipfile();
    
    //add files to the zip, passing file contents, not actual files
    $zip->addFile($file_content, $file_name);
    
    ...
    
    //prepare the proper content type
    header("Content-type: application/octet-stream");
    header("Content-Disposition: attachment; filename=my_archive.zip");
    header("Content-Description: Files of an applicant");
    
    //get the zip content and send it back to the browser
    echo $zip->file();
    

    This script allows downloading of a zip, without the need of having the files as real files or saving the zip itself as a file.

    It is a shame that this functionality is not part of a more generic PHP library.

    Here is a link to the zip.lib.php file from the phpmyadmin source: https://github.com/phpmyadmin/phpmyadmin/blob/RELEASE_4_5_5_1/libraries/zip.lib.php

    UPDATE: Make sure you remove the following check from the beginning of zip.lib.php as otherwise the script just terminates:

    if (! defined('PHPMYADMIN')) {
        exit;
    }
    

    UPDATE: This code is available on the CodeIgniter project as well: https://github.com/patricksavalle/CodeIgniter/blob/439ac3a87a448ae6c2cbae0890c9f672efcae32d/system/helpers/zip_helper.php

    0 讨论(0)
  • 2020-11-27 05:25

    Regarding your comment that php://temp works for you except when you close it, try keeping it open, flushing the output, then rewind it back to 0 and read it.

    Look here for more examples: http://us.php.net/manual/en/function.tmpfile.php

    Also research output buffering and capturing: http://us.php.net/manual/en/function.ob-start.php

    0 讨论(0)
  • 2020-11-27 05:28

    You need to use ZipArchive::addFromString - if you use addFile() the file is not actually added until you go to close it. (Horrible bug IMHO, what if you are trying to move files into a zip and you delete them before you close the zip...)
    The addFromString() method adds it to the archive immediately.

    0 讨论(0)
  • 2020-11-27 05:29

    Is there really a performance issue here, or does it just offend your sense of rightness? A lot of processes write temporary files and delete them, and often they never hit the disk due to caching.

    A tempfile is automatically deleted when closed. That's it's nature.

    There are only two ways I can think of to create a zip file in memory and serve it and both are probably more trouble than they are worth.

    • use a ram disk.
    • modify the ziparchive class to add a method that does everything the close() method does, except actually close the file. (Or add a leave-open parameter to close()).
      This might not even be possible depending on the underlying C libraries.
    0 讨论(0)
  • 2020-11-27 05:49

    what are you using to generate the archive? You might be able to use the stream php://temp or php://memory to read and write to/from the archive.

    See http://php.net/manual/en/wrappers.php.php

    0 讨论(0)
提交回复
热议问题