9

如果我尝试从我的 S3 存储桶中获取一个不存在的对象,Amazon PHP SDK 2 会给我一个非常丑陋的错误。对我来说很方便,但对最终用户没有任何意义......

例如:

$s3 = $aws->get('s3');

$result = $s3->getObject(array(
    'Bucket' => 'my bucket',
    'Key'    => 'path/to/file'
));

错误:

致命错误:未捕获的 Aws\S3\Exception\NoSuchKeyException:AWS 错误代码:NoSuchKey,状态代码:404,AWS 请求 ID:xxxxxxxxxxxxx,AWS 错误类型:客户端,AWS 错误消息:指定的密钥不存在。在第 89 行抛出 AWS/vendor/aws/aws-sdk-php/src/Aws/Common/Exception/NamespaceExceptionFactory.php

有没有一种方法可以确定是否存在错误并打印一条有意义的消息而不是上述消息?

4

3 回答 3

9

我突然想到要试试这个:

try {
    $result = $s3->getObject(array(
        'Bucket' => 'my bucket',
        'Key'    => 'path/to/file'
    ));
} catch (Exception $e) {
   // I can put a nicer error message here  
}
于 2013-04-12T10:31:25.590 回答
6

调用 AWS 开发工具包的方法时发生的所有错误都通过引发异常来指示。如果要处理错误,可以捕获这些异常。

在最简单的情况下,您可能只想捕获Exception

try {
    $result = $s3->getObject(array(
        'Bucket' => 'my bucket',
        'Key'    => 'path/to/file'
    ));
}
catch (Exception $e) {
    echo 'Oops, something went wrong';
}

但是,如果您只想处理某些预期的异常,同时让其他人冒泡并让您的应用程序崩溃,那么事情就会变得更加微妙。

首先, AWS 命名空间中的几十个命名空间中的每一个都包含一个Exception命名空间,其中定义了异常类。每个命名空间中的这些类之一是 Amazon 称之为命名空间的默认服务异常类,所有其他异常都从该类继承。

例如,S3 有Aws\S3\Exception命名空间S3Exception。EC2 具有Aws\Ec2\Exception命名空间Ec2Exception

请注意,捕获这些异常之一而不是基Exception类会立即阻止我们捕获某些错误!由于服务器的错误响应,会引发特定于服务的异常;连接失败异常不会从它们继承。例如,如果您尝试在没有 Internet 连接的情况下运行以下代码...

try {
    $result = $s3->getObject(array(
        'Bucket' => 'my bucket',
        'Key'    => 'path/to/file'
    ));
}
catch (S3Exception $e) {
    echo 'Oops, something went wrong';
}

...那么异常将不会被捕获(因为它将是一个Guzzle\Http\Exception\CurlException,而不是 S3Exception)并且程序将崩溃。出于这个原因,如果您捕获这些异常只是为了向用户提供一般的失败消息,您可能应该捕获Exception.

让我们回到如何处理特定错误的问题。对于大多数命名空间,答案是将为该错误定义一个异常类,您应该抓住它。例如,假设我们再次使用 S3getObject方法,并且想要在我们请求的存储桶不存在时做一些事情。查看S3 Exception 命名空间文档,我们看到有一个NoSuchBucketException我们可以捕获:

try {
    $result = $s3->getObject(array(
        'Bucket' => 'my bucket',
        'Key'    => 'path/to/file'
    ));
}
catch (NoSuchBucketException $e) {
    echo 'There is no such bucket.';
}

(在实践中,通过反复试验比仔细阅读文档更容易找出哪些操作可以引发哪些异常。)

最后,值得一提的是 EC2 API。与所有其他服务不同,EC2 命名空间仅包含一个异常类,即Ec2Exception. 如果您想捕获并处理特定错误,则需要检查异常对象以找出您正在处理的错误类型。您可以通过检查getExceptionCode()异常方法返回的值来做到这一点。

例如,我最近编写的脚本中的(修改的)片段授予指定 IP 访问我们的 MySQL 服务器的权限:

try {
    $result = $ec2->authorizeSecurityGroupIngress([
        'GroupName' => 'mygroup',
        'IpProtocol' => 'tcp',
        'ToPort' => 3306,
        'CidrIp' => $ip . "/32",
    ]);
}
catch (Ec2Exception $e) {
    if ($e->getExceptionCode() == 'InvalidPermission.Duplicate') {
        echo "IP already has requested permission.";
    }
    else {
        // Don't know how to deal with this error; let's crash
        throw $e;
    }
}

请注意,InvalidPermission.DuplicateAWS PHP SDK 文档中未列出可能的异常代码(如本例所示),但您可以通过反复试验或从EC2 API 本身的文档中找到它们,其中每个 API 操作的页面都包含一个“错误部分列出了它可以返回的错误代码。

于 2014-09-07T22:52:07.410 回答
2

您也可以使用此方法: $response = $s3->doesObjectExist( $bucket, $key );

如果对象存在,它将返回一个布尔值 true 响应。

dosObjectExist 的 AWS 文档

于 2015-01-30T17:28:01.950 回答