2

我正在尝试将许多图像上传到 S3 存储桶。考虑到速度,我希望通过将数据保存在内存中来减少磁盘读取和写入的次数。为此,我想出了以下方案:

//fetch binary image data from remote URL
$contents = file_get_contents("http://somesite.com/image.jpg");
//trim the image as per: http://stackoverflow.com/a/15104071/568884
$out = shell_exec('echo ' . base64_encode($contents) . " | base64 -d | convert - -fuzz 10% -trim jpeg:-");
//create a temporary resource to pass to S3's inputResource() method.
$resource = fopen('php://temp', 'r+');
//write the binary data into the empty resource.
fwrite($resource, $out);
//pass the resource and length of binary data into inputResource()
$ir = $this->s3->inputResource($resource, strlen($out));
//finally transfer the resource from machine to S3.
$this->s3->putObject($ir, $bucket, $s3_path, S3::ACL_PUBLIC_READ);

错误是:S3::putObject(): [RequestTimeout] 您与服务器的套接字连接未在超时期限内读取或写入。空闲连接将被关闭,数据不会写入 S3。

如果我将 $out 的分配简单地替换为一个空字符串:$out = "";然后,该库按预期成功地将 0 字节文件写入 S3。

我正在使用CodeIgniter S3库......它只是 AWS S3 API afaik 的包装器。

4

2 回答 2

1

您正在将文件句柄传递$resource给库,但是,您首先写入它,以便文件指针位于文件末尾。

该库可能无法处理这种极端情况(它的源代码表明)。

rewind($resource)您可以在写入文件后但在将其传递到 S3 库之前尝试访问该文件。

如果你想加快一点速度,你可以通过切换php://tempphp://memory. 有关详细信息和选项,php://请参阅包装器文档

顺便说一句,S3 库。不是官方的。如果您启用通知和警告,您可能会看到报告的一些问题,因为它仍然包含 PHP 4 代码。

于 2013-03-10T12:21:05.560 回答
0

RequestTimeout 错误的可能来源可能是您对 putObject 的调用指定的 Content-Length 与发送的实际数据不同。根据AWS 论坛中的亚马逊代表:

触发 RequestTimeout 错误的一种方法是发送一个 PUT 请求,该请求指定 Content-Length 为 2,但在请求正文中仅包含 1 个字节的对象数据。在等待剩余字节到达 20 秒后,Amazon S3 将响应 RequestTimeour 错误。

因此,当您使用 strlen() 函数时,您的临时文件可能会报告错误的长度,并且此错误值导致 S3 响应异常。

根据对strlen() 的 php 文档的评论,该函数可能会报告文件中错误的字节数,因为它假定字符串始终是 ASCII:

如果是这种情况,它可能会将二进制数据视为 unocode 字符串并返回错误值

尝试用调用mb_strlen() 替换 strlen(),它应该总是报告正确的字节数。

于 2013-03-05T10:34:02.863 回答