用于 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 解决方案不起作用。

谢谢!

最佳 格什

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

  1. 设置 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 环境。

  1. 在 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);
}

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