【问题标题】:php file_get_contents(): content truncated from 2147483648 to 2147483647 bytesphp file_get_contents():内容从 2147483648 截断到 2147483647 字节
【发布时间】:2015-06-10 16:23:41
【问题描述】:

我要创建 2GB 文件的 zip 文件时如何找出问题。

错误

file_get_contents():内容从 2147483648 截断到 2147483647 字节

致命错误:内存不足(已分配 2151677952)(试图分配 18446744071562067968 字节)在

我正在使用专用服务器并且已经设置了memory_limit,max_execution_time,max_upload_filesize,max_post_size。但这对我不起作用。请检查我的代码并让我知道我做错了什么-

创建新的 zip 对象

    $zip = new ZipArchive();

    # create a temp file & open it
    $tmp_file = tempnam('.','');
    $zip->open($tmp_file, ZipArchive::CREATE);

    # loop through each file
    foreach($files as $file){
        # download file
        $download_file = file_get_contents($file_path.'/'.$file);
        #add it to the zip
        $zip->addFromString(basename($file_path.'/'.$file),$download_file);
    }

    # close zip
    $zip->close();
    $zip_name = $last_seg.'.zip';
    # send the file to the browser as a download
    header("Content-disposition: attachment; filename=$zip_name");
    header('Content-type: application/zip');
    readfile($tmp_file);

【问题讨论】:

  • 试试这里提供的解决方案stackoverflow.com/questions/6282887/…这是一个内存限制问题,而且您的文件太大。
  • 同时检查这个问题/答案stackoverflow.com/questions/5745255/…
  • 非常感谢,这可能是重复的问题,但在尝试了这里所有可用的解决方案后,我又问了一遍。我试图从 WHM 增加内存限制但没有工作:(
  • 消息说您正在尝试分配 18446744 TeraBytes。我认为您不仅应该调整内存限制,还应该购买更多的 RAM...

标签: php file http-headers zip memory-limit


【解决方案1】:

我将 $zip->addFromString() 更改为 $zip->addFile() 因为您不需要读取内容文件来添加文件,我用 3 部电影测试您的代码并且不起作用(我有同样的错误)但是当我使用$zip->addFile() 一切正常,我可以下载 3gb 的 zip 文件。

我需要使用set_time_limit(0);

如果您想测试此代码,只需更改以下值:

$files //Array of files name $file_path //Path where your files ($files) are placed $last_seg //The name of your zip file

<?php

    set_time_limit(0);

    $files = array('Exodus.mp4', 'the-expert.webm', 'what-virgin-means.webm');
    $file_path = 'zip';
    $last_seg = 'test';

    $zip = new ZipArchive();

    # create a temp file & open it
    $tmp_file = tempnam('.','');
    $zip->open($tmp_file, ZipArchive::CREATE);

    # loop through each file
    foreach($files as $file){
        $zip->addFile($file_path.'/'.$file, $file);
    }

    # close zip
    $zip->close();
    $zip_name = $last_seg.'.zip';
    # send the file to the browser as a download
    header("Content-disposition: attachment; filename=$zip_name");
    header('Content-type: application/zip');
    readfile($tmp_file);

?>

您可以在以下位置阅读更多信息:

http://php.net/manual/en/ziparchive.addfile.php

【讨论】:

  • @jenifer 不客气,不要忘记检查是否已接受;-) 如果您不知道如何阅读此stackoverflow.com/tour
  • @jenifer 记得接受答案,记得你说它很有效 ;-)
  • @jenifer 如果您不知道如何检查已接受的答案,请阅读此stackoverflow.com/tour
【解决方案2】:

您将永远无法分配比 PHP_INT_MAX 更多的内存。因此,如果 file_gets_content 内部不限于签名的 int 32 位,那么也许 linux x64 版本的 PHP 可以处理此问题,但在 Windows 或 32 位系统上,如果没有流式传输,您将没有机会实现此目标。

这样的事情可能会起作用:(尚未测试)

$fr = fopen("http://...", "r");
$fw = fopen("zip://c:\\test.zip#test", "w");

while(false !== ($buffer = fread($fr, 8192)))
{
  fwrite($fw, $buffer, strlen($buffer));
}

fclose($fr);
fclose($fw);

好吧,显然 PHP 没有为 zip 流提供模式“+w”...您的最后一个选择是,将整个文件写入临时文件(像我一样通过流式传输,没有 file_get_contents)在将其提供给外部程序(使用 system() 或 popen 调用...)或使用另一种压缩格式(显然 php 支持 zlib ant bzip2 的写入流操作)或使用 php 的外部库之前。

【讨论】:

  • 谢谢你,mathieu,所以我需要更改我的代码?你知道我应该在这里做什么更改吗?或任何我可以找到参考的链接?
  • 基本上,你需要打开一个zip流来写入,然后用php可以处理的缓冲区重复读取输入文件......我不确定是否可以没有外部库.
【解决方案3】:

尝试将此行放在代码的开头:

ini_set("memory_limit", -1);

参考这个问题 Fatal error: Out of memory (allocated 1134559232) (tried to allocate 32768 bytes) in X:\wamp\www\xxx

【讨论】:

  • 好的,非常感谢您抽出宝贵的时间,我会试试这个。我已经在 WHM 上尝试过 memory_limit = -1,但没有成功。
  • -1 18446744071562067968的大小会占用系统内存。添加更多内存以便能够将文件读入内存总是一个坏主意。
猜你喜欢
  • 1970-01-01
  • 2020-08-20
  • 2023-03-22
  • 2014-12-04
  • 1970-01-01
  • 2012-12-13
相关资源
最近更新 更多