用于 php blob 下载的 Azure SDK 导致内存不足
Azure SDK for php blob download causes out of memory
我正在使用 Azure blob 存储在云中存储巨大的 pdf 和 zip 文件。
我通过 php 的 azure sdk 访问文件并将文件直接推送给用户(当然用户不应该看到文件的来源,所以我不会将他重定向到 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 解决方案不起作用。
谢谢!
最佳
格什
据我了解,由于下载的文件越大,程序占用的内存就越多。在这种情况下,我们可以采取这些措施来克服内存耗尽错误:
- 设置 memory_limit 值。
有一个名为 memory_limit
的 PHP env 配置来限制可以分配的内存。我们可以使用以下代码在 php 页面中设置 memory_limit 值:
ini_set("memory_limit","200M");
如果您不想设置文件大小,可以将memory_limit值设置为“-1”,就像:
ini_set("memory_limit","-1");
另一种方法,我们可以在配置文件中放大它(如php.ini)。此 official guide 告诉您如何配置 PHP 环境。
- 在 chucks 中下载文件
我们也可以在 chucks 中下载大的 blob 以减少内存开销。
查看SDK源码BlobRestProxy.php
,里面有一个获取Blob的函数public function getBlob($container, $blob, $options = null)
,我们可以在$options
中设置额外的参数,每次都分片获取Blob .这是我的代码片段:
$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);
}
如有任何疑虑,请随时告诉我。
我正在使用 Azure blob 存储在云中存储巨大的 pdf 和 zip 文件。 我通过 php 的 azure sdk 访问文件并将文件直接推送给用户(当然用户不应该看到文件的来源,所以我不会将他重定向到 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 解决方案不起作用。
谢谢!
最佳 格什
据我了解,由于下载的文件越大,程序占用的内存就越多。在这种情况下,我们可以采取这些措施来克服内存耗尽错误:
- 设置 memory_limit 值。
有一个名为 memory_limit
的 PHP env 配置来限制可以分配的内存。我们可以使用以下代码在 php 页面中设置 memory_limit 值:
ini_set("memory_limit","200M");
如果您不想设置文件大小,可以将memory_limit值设置为“-1”,就像:
ini_set("memory_limit","-1");
另一种方法,我们可以在配置文件中放大它(如php.ini)。此 official guide 告诉您如何配置 PHP 环境。
- 在 chucks 中下载文件
我们也可以在 chucks 中下载大的 blob 以减少内存开销。
查看SDK源码BlobRestProxy.php
,里面有一个获取Blob的函数public function getBlob($container, $blob, $options = null)
,我们可以在$options
中设置额外的参数,每次都分片获取Blob .这是我的代码片段:
$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);
}
如有任何疑虑,请随时告诉我。