用于php blob下载的Azure SDK会导致内存不足

时间:2015-07-18 09:37:12

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

我正在使用Azure blob存储将巨大的pdf和zip文件存储在云端。 我通过azure sdk访问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

有没有更好的方法可以为用户提供云存储文件而无需识别它?

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

谢谢!

最佳

Gesh

1 个答案:

答案 0 :(得分:1)

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

  1. 设置memory_limit值。
  2. 有一个名为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中下载文件
    2. 我们还可以在chucks中下载大blob以减少内存开销。

      要查看BlobRestProxy.php中的SDK源代码,有一个函数用于获取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);
      }
      

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