我正在尝试将许多图像上传到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的包装。
答案 0 :(得分:1)
您正在将文件句柄$resource
传递给库,但是,您首先写入它,以便文件指针位于文件的末尾。
该库可能无法处理该边缘情况(它的源代码表明)。
您可以在写入文件后尝试rewind($resource)
文件,但在将文件传递到S3库之前。
如果你想加快这一点,你可以通过将php://temp
切换到php://memory
来让PHP使用内存来处理较小的文件。有关详细信息和选项,请参阅the php://
wrapper docs。
S3库btw。不是官方的。如果启用通知和警告,您可能会看到报告的一些问题,因为它仍然包含PHP 4代码。
答案 1 :(得分:0)
RequestTimeout错误的一个可能来源可能是您对putObject的调用指定的内容长度与发送的实际数据不同。根据{{3}}中的亚马逊代表:
触发RequestTimeout错误的一种方法是发送PUT 请求指定Content-Length为2但仅包含1个字节 请求正文中的对象数据。等了20秒之后 剩下的字节到达,Amazon S3将使用RequestTimeour进行响应 错误。
因此,当您使用strlen()函数时,您的临时文件可能会报告错误的长度,并且此错误值导致S3响应异常。
根据对the AWS forums的评论,该函数可以报告文件中错误的字节数,因为它假设字符串总是ASCII:
如果是这种情况,它可能会将二进制数据视为unocode字符串和 返回错误的值
尝试用php documentation for strlen()调用替换strlen(),它应该始终报告正确的字节数。