Azure SDK for php blob 下载导致内存不足
Posted
技术标签:
【中文标题】Azure SDK for php blob 下载导致内存不足【英文标题】:Azure SDK for php blob download causes out of memory 【发布时间】: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 解决方案不起作用。
谢谢!
最好的 格什
【问题讨论】:
【参考方案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环境。
-
在卡盘中下载文件
我们还可以在卡盘中下载大型 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);
如有任何疑问,请随时告诉我。
【讨论】:
您好,谢谢您的回答。第一个选项是不可能的,我不能增加内存限制。我尝试了第二种解决方案,但我得到了同样的错误,不管 chunk_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 => null [private] _snapshot => null [private] _accessCondition => null [private] _computeRangeMD5 => null [private] _rangeStart => (int) 0 [private] _rangeEnd => (int) 1048575 object(WindowsAzure\Blob\Models\GetBlobOptions) [private] _leaseId => null [private] _snapshot => null [private] _accessCondition => null [private] _computeRangeMD5 => null [private] _rangeStart => (int) 1048576 [private] _rangeEnd => (int) 2097151
以上是关于Azure SDK for php blob 下载导致内存不足的主要内容,如果未能解决你的问题,请参考以下文章
Azure Blob PHP SDK - 直接从自定义多部分 API 请求上传到 Azure 存储
Azure Blob Storage SDK for .NET BlobClient.UploadAsync 总是抛出异常,但总是上传文件
如何在 Azure blob 下载中获取 blob 下载进度