无法使用图片的直接网址将图片上传到S3存储桶

时间:2015-12-13 12:56:11

标签: php amazon-web-services amazon-s3

这是我的代码,适用于表单上传(通过$ _FILES)(我省略了代码的那部分,因为它无关紧要):

$file = "http://i.imgur.com/QLQjDpT.jpg";

$s3 = S3Client::factory(array(
    'region' => $region,
    'version' => $version
));  

        try {

            $content_type = "image/" . $ext;

            $to_send = array();

            $to_send["SourceFile"] = $file;

            $to_send["Bucket"] = $bucket;
            $to_send["Key"] = $file_path;
            $to_send["ACL"] = 'public-read';
            $to_send["ContentType"] = $content_type;

            // Upload a file.
            $result = $s3->putObject($to_send);

正如我所说,如果文件是$_FILES["files"]["tmp_name"],这可行,但如果$ file是带有未捕获异常'Aws \ Exception \ CouldNotCreateChecksumException'且消息为'A sha256 checksum could not be calculated for the provided upload body, because it was not seekable. To prevent this error you can either 1) include the ContentMD5 or ContentSHA256 parameters with your request, 2) use a seekable stream for the body, or 3) wrap the non-seekable stream in a GuzzleHttp\Psr7\CachingStream object. You should be careful though and remember that the CachingStream utilizes PHP temp streams. This means that the stream will be temporarily stored on the local disk.'的有效图像网址,则会失败。有谁知道为什么会这样?什么可能会关闭? Tyvm求助!

2 个答案:

答案 0 :(得分:3)

您必须先将文件下载到运行PHP的服务器上。 S3上传仅适用于本地文件 - 这就是def func(f1:int, f2:str, s:str) -> bool: return isinstance(f2, int) def func2(fn:Callable[[int, int, str], bool]): print(fn(42, 42, 'hello mum')) func2(func) # Correctly flagged as a type error 工作的原因 - 它是PHP服务器本地的文件。

答案 1 :(得分:3)

对于寻找选项#3(CachingStream)的任何人,您可以传递PutObject命令Body流而不是源文件。

use GuzzleHttp\Psr7\Stream;
use GuzzleHttp\Psr7\CachingStream;
...
$s3->putObject([
    'Bucket'        => $bucket,
    'Key'           => $file_path,
    'Body'          => new CachingStream(
        new Stream(fopen($file, 'r'))
    ),
    'ACL'           => 'public-read',
    'ContentType'   => $content_type,
]);

或者,您可以使用guzzle请求文件。

$client = new GuzzleHttp\Client();
$response = $client->get($file);

$s3->putObject([
    'Bucket'        => $bucket,
    'Key'           => $file_path,
    'Body'          => $response->getBody(),
    'ACL'           => 'public-read',
    'ContentType'   => $content_type,
]);