【问题标题】:Azure SDK for php blob download causes out of memoryAzure SDK for php blob 下载导致内存不足
【发布时间】:2015-10-08 00:00:13
【问题描述】:

我正在使用 Azure blob 存储在云中存储大量 pdf 和 zip 文件。 我通过 azure sdk for php 访问文件并将文件直接推送给用户(当然用户不应该看到文件来自哪里,所以我不会将他重定向到 Microsoft url)。 我的代码如下所示:

$blobRestProxy = ServicesBuilder::getInstance()->createBlobService($this->azureConfig['connectionString']);

$blob = $blobRestProxy->getBlob($container, $blobName);
$properties = $blobRestProxy->getBlobProperties($container, $blobName);

$size = $properties->getProperties()->getContentLength();
$mime = $properties->getProperties()->getContentType();
$stream = $blob->getContentStream();

header("Pragma:no-cache");
header("Cache-Control: no-cache, must-revalidate");
header("Content-type: $mime");
header("Content-length: $size");

fpassthru($stream);

对于小文件,完全没有问题,对于较大的文件,我得到这个错误:

Fatal error: Out of memory (allocated 93323264) (tried to allocate 254826985 bytes) in \vendors\azure-sdk-for-php\WindowsAzure\Common\Internal\Utilities.php on line 450

有没有更好的方法在用户不认识的情况下通过 php 向用户提供云存储文件?

我已经找到了这个讨论 https://github.com/Azure/azure-sdk-for-php/issues/729,但是 curl 解决方案不起作用。

谢谢!

最好的 格什

【问题讨论】:

    标签: php azure out-of-memory azure-blob-storage


    【解决方案1】:

    据我了解,由于下载的文件更大,程序会消耗更多的内存。在这种情况下,我们可以采取这些措施来克服内存耗尽错误:

    1. 设置 memory_limit 值。

    有一个名为memory_limit 的PHP 环境配置来限制可以分配的内存。我们可以使用代码在php页面中设置memory_limit值:

    ini_set("memory_limit","200M");
    

    如果您不想设置文件大小,可以将 memory_limit 值设置为“-1”,就像:

    ini_set("memory_limit","-1");
    

    另一种方法,我们可以在配置文件(如 php.ini)中将其放大。这个official guide告诉你如何配置PHP环境。

    1. 在卡盘中下载文件

    我们还可以在卡盘中下载大型 blob 以减少内存开销。

    查看BlobRestProxy.php中的SDK源码,有一个用于获取Blob的函数public function getBlob($container, $blob, $options = null),我们可以在$options中设置额外的参数,每次都分片获取Blob。这是我的代码 sn-p:

    $properties = $blobRestProxy->getBlobProperties($container, $blobName);
    $size = $properties->getProperties()->getContentLength();
    $mime = $properties->getProperties()->getContentType();
    $chunk_size = 1024 * 1024;
    $index = 0;
    //$stream = "";
    
    header("Pragma: public");
    header('Content-Disposition: attachment; filename="' . $blobName . '"');
    header('Expires: 0');
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Content-Transfer-Encoding: binary");
    header("Content-type: $mime");
    header("Content-length: $size");
    ob_clean();
    
    while ($index < $size) {
           $option = new GetBlobOptions();
           $option->setRangeStart($index);
           $option->setRangeEnd($index + $chunk_size - 1);
           $blob = $blobRestProxy->getBlob($container, $blobName, $option);
           $stream_t = $blob->getContentStream();
           $length = $blob->getProperties()->getContentLength();
           $index += $length;
           flush();
           fpassthru($stream_t);
    }
    

    如有任何疑问,请随时告诉我。

    【讨论】:

    • 您好,谢谢您的回答。第一个选项是不可能的,我不能增加内存限制。我尝试了第二种解决方案,但我得到了同样的错误,不管 chu​​nk_size 有多大。我不知道为什么,也许 BlobOptions 不能正常工作。
    • 嗨@Gesh,BlobOptions 确实有自己的类类型Models\GetBlobOptions,并且还探索了一些设置\获取属性的功能。我们可以看到[源代码](github.com/Azure/azure-sdk-for-php/blob/master/WindowsAzure/…)。当然,要创建GetBlobOptions,我们需要首先引用命名空间use WindowsAzure\Blob\Models\GetBlobOptions;。顺便说一句,如果有任何错误消息显示给我,那就更好了。
    • 嗨@Gary,我当然添加了使用WindowsAzure\Blob\Models\GetBlobOptions;。所以我得到的错误是:Error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 254826985 bytes) File: /vendors/azure-sdk-for-php/WindowsAzure/Common/Internal/Utilities.php Line: 450 所以我之前得到了同样的错误。
    • 它似乎没有被分割成块。我们可以在getBlob之前var_export($option)检查范围是否在循环中。
    • 选项如下所示:object(WindowsAzure\Blob\Models\GetBlobOptions) { [private] _leaseId =&gt; null [private] _snapshot =&gt; null [private] _accessCondition =&gt; null [private] _computeRangeMD5 =&gt; null [private] _rangeStart =&gt; (int) 0 [private] _rangeEnd =&gt; (int) 1048575 } object(WindowsAzure\Blob\Models\GetBlobOptions) { [private] _leaseId =&gt; null [private] _snapshot =&gt; null [private] _accessCondition =&gt; null [private] _computeRangeMD5 =&gt; null [private] _rangeStart =&gt; (int) 1048576 [private] _rangeEnd =&gt; (int) 2097151 }
    猜你喜欢
    • 2015-06-20
    • 1970-01-01
    • 2014-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-13
    • 2017-03-15
    • 2012-09-11
    相关资源
    最近更新 更多