【问题标题】:Manipulate an Archive in memory with PHP (without creating a temporary file on disk)使用 PHP 操作内存中的存档(无需在磁盘上创建临时文件)
【发布时间】:2010-11-14 09:53:25
【问题描述】:

我正在尝试在 PHP 中即时生成存档并立即将其发送给用户(不保存)。我认为没有必要在磁盘上创建文件,因为我发送的数据无论如何都不是持久的,但是,在搜索网络时,我不知道如何。我也不关心文件格式。

所以,问题是:

是否可以在 php 脚本中创建和操作内存中的文件存档,而无需在此过程中创建临时文件?

【问题讨论】:

  • 这个存档可以只包含一个文件还是多个文件?
  • 在我的具体情况下,它包含多个。另外我认为“任意”大型档案(逐项)的解决方案更有趣(在我的情况下,我可以使用临时文件,但是那些必须使用服务器来访问文件系统的人呢?受限制)?

标签: php memory archive disk


【解决方案1】:

我遇到了同样的问题,但最后找到了一个有点晦涩的解决方案,并决定在这里分享。

我遇到了很棒的 zip.lib.php/unzip.lib.php 脚本,它们与 phpmyadmin 一起提供,位于“库”目录中。

使用zip.lib.php 对我来说是一种魅力:

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

此脚本允许下载 zip,而无需将文件作为真实文件或将 zip 本身保存为文件。

遗憾的是,此功能不是更通用的 PHP 库的一部分。

这里是来自 phpmyadmin 源的zip.lib.php 文件的链接: https://github.com/phpmyadmin/phpmyadmin/blob/RELEASE_4_5_5_1/libraries/zip.lib.php

更新: 确保从 zip.lib.php 的开头删除以下检查,否则脚本将终止:

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

更新: 该代码也可用于 CodeIgniter 项目: https://github.com/patricksavalle/CodeIgniter/blob/439ac3a87a448ae6c2cbae0890c9f672efcae32d/system/helpers/zip_helper.php

【讨论】:

  • 您应该提到您需要修改它以删除对“PHPMYADMIN”常量定义的检查,否则它将结束脚本。我花了一秒钟多的时间来解决这个问题。
  • 谢谢,似乎是在我发布上述答案后引入了检查。我更新了答案。
  • 像魅力一样工作。我把它变成了一个 Codeigniter 助手,一点问题都没有。
  • 我用这段代码创建了一个 Codeigniter 助手。为我工作。这是:github.com/patricksavalle/CodeIgniter/blob/…
【解决方案2】:

您使用什么来生成存档?您也许可以使用流 php://temp 或 php://memory 来读写存档。

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

【讨论】:

  • 目前,我正在使用 php zip 扩展并在每次提供下载时编写一个临时文件。我尝试使用 php://temp 包装器(认为它优于 php://memory,因为有大量数据,临时文件是个好主意,即使在限制 fs 访问时主机也可能允许使用它。我遇到了我必须关闭 zipfile 的问题,这似乎释放了 php://temp/ 中的所有内容。(在关闭之前和之后从 zipfile 中读取给了我 0 个字节。)无论如何,我不在乎我的库使用,只要它有效。当然,PHP 内部是首选。
【解决方案3】:

关于您的评论 php://temp 对您有效,除非您关闭它,请尝试保持打开状态,刷新输出,然后将其倒回 0 并阅读它。

查看更多示例:http://us.php.net/manual/en/function.tmpfile.php

还研究输出缓冲和捕获:http://us.php.net/manual/en/function.ob-start.php

【讨论】:

    【解决方案4】:

    您需要使用ZipArchive::addFromString - 如果您使用addFile(),则在您关闭文件之前不会实际添加该文件。 (可怕的错误恕我直言,如果您尝试将文件移动到 zip 中并在关闭 zip 之前将其删除...)
    addFromString() 方法立即将其添加到存档中。

    【讨论】:

      【解决方案5】:

      这里真的存在性能问题,还是只是冒犯了您的正确感?很多进程写入临时文件并删除它们,并且由于缓存,它们通常永远不会命中磁盘。

      临时文件在关闭时会自动删除。这就是它的本性。

      我能想到的只有两种方法可以在内存中创建一个 zip 文件并提供它,这两种方法都可能比它们的价值更麻烦。

      • 使用内存盘。
      • 修改 ziparchive 类以添加一个方法来完成 close() 方法所做的所有事情,除了实际上关闭文件。 (或者在 close() 中添加一个 leave-open 参数)。
        这甚至可能无法实现,具体取决于底层 C 库。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-05-10
        • 1970-01-01
        • 1970-01-01
        • 2021-05-03
        • 2019-03-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多