【问题标题】:PHP fails fopen if the file is large如果文件很大,PHP 会失败 fopen
【发布时间】:2015-01-08 00:04:34
【问题描述】:

我正在使用 PHP 的 Google App Engine 上运行应用程序。

我正在使用以下代码从 API 下载文件:

$context = [
   "http" => [
   "method" => "GET",
   "header" => "Authorization: ".$token."\r\n",
   "follow_location"=>1,
   "timeout"=>600,
   "ignore_errors"=>1
              ]
            ];
$context = stream_context_create($context);
$sourceFile = fopen($location,"r", false,$context) or die("no handle");

此代码之后是对另一个资源的块读取和写入(基本上我将文件存储在 Google 存储上)。

$destinationFile = fopen($filename,"w");
while ($buffer = fread($sourceFile, 1048576)) {
      fwrite($destinationFile,$buffer);
} 

此代码的问题在于,如果文件很小(大约低于 30 MB),它确实可以正常工作,但如果文件很大,则 fopen 会失败。我收到“无句柄”消息。

这有点奇怪,因为我明确避免使用 file_get_contents 将整个文件下载到内存中,我不明白为什么 fopen 会失败!

你能帮帮我吗?谢谢

【问题讨论】:

  • 另请注意,如果在本地(而不是在 Google App Engine 上)执行此代码,即使在大文件上也能完美运行。所以肯定是App Engine的一些配置...

标签: php google-app-engine


【解决方案1】:

限制为 32 兆字节。这就是它失败的原因。显然,该限制不适用于本地,因此它适用于开发服务器。

https://cloud.google.com/appengine/docs/python/urlfetch/#Python_Quotas_and_limits

【讨论】:

  • 但是我没有得到请求的完整文件:我只是得到一个 fopen 然后分块读取它。你是说 HTTP 请求会得到完整的响应吗?如果是这样,我应该如何从 API 下载请求中获取一个大文件并将其发布到 Google Storage 上?有什么推荐的方法吗?谢谢
  • 好吧,看起来好像 HTTP 请求得到了完整的响应。我不做PHP所以没有太多帮助。您可以在 python 中设置“Accept-Ranges”和/或“Accept-Length”标头,所以大概在 PHP 中有类似的东西来获取部分内容。
  • 我尝试在标题中添加$rng= 'HTTP/1.1 206 Partial Content\r\nAccept-Ranges: bytes\r\nContent-Range: bytes 0-7999999/37762382\r\nContent-Length: 8000000\r\n'; 以获得前 8MB,但它甚至无法在本地工作 - 也许 API 不支持可恢复下载 - 顺便说一下,它甚至不报告内容 -长度
  • 外部服务可能会也可能不会尊重这些标头。
  • 如果您联系的服务器支持流式传输范围,则它们应该可以正常工作。我们在随 SDK 提供的云存储客户端中使用相同的 URLFetch API,并使用范围请求来支持任意长度的文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-26
  • 1970-01-01
  • 2019-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多