2013-04-10 37 views
7

Nếu tôi cố gắng lấy một đối tượng từ nhóm S3 không tồn tại, Amazon PHP SDK 2 mang lại cho tôi một lỗi khá xấu. Handy cho tôi nhưng có ý nghĩa gì đối với người dùng cuối ...Xử lý lỗi trong AWS PHP SDK 2

Ví dụ:

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

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

Lỗi:

Fatal error: Uncaught Aws\S3\Exception\NoSuchKeyException: AWS Error Code: NoSuchKey, Status Code: 404, AWS Request ID: xxxxxxxxxxxxx, AWS Error Type: client, AWS Error Message: The specified key does not exist. thrown in AWS/vendor/aws/aws-sdk-php/src/Aws/Common/Exception/NamespaceExceptionFactory.php on line 89

Có cách nào mà tôi có thể xác định xem có phải là một lỗi và in một thông điệp có ý nghĩa hơn là ở trên?

+0

Nếu bạn kích hoạt trang web trên S3, có một tùy chọn để bạn có thể chuyển hướng File Not Found lỗi đến một trang (trong trường hợp của tôi, tôi sử dụng một file jpg nói rằng "File Not Found", Vì vậy, điều này sẽ làm việc cho hình ảnh quá) –

+0

Cảm ơn @Alvin K. Không chắc chắn như thế nào mà sẽ làm việc cho tôi như tôi có nhiều loại tập tin để trở về một tập tin JPG sẽ không thực sự giúp tôi. Nhưng dù gì cũng cảm ơn. –

+0

Vì tệp jpg đã được sửa, kiểm tra md5 sẽ xác định tệp nào được trả lại và bạn "bắt" lỗi 404 này. –

Trả lời

7

Nó đột nhiên xảy ra với tôi thử này:

try { 
    $result = $s3->getObject(array(
     'Bucket' => 'my bucket', 
     'Key' => 'path/to/file' 
    )); 
} catch (Exception $e) { 
    // I can put a nicer error message here 
} 
+0

Ngoại lệ sẽ chỉ xảy ra nếu getObject() không kết nối, thường nó sẽ trả về một đối tượng, cho dù đó là một XML có mã lỗi hoặc FileNotFound.jpg hoặc tệp thực sự bạn đang tìm kiếm. –

+0

Cảm ơn Alvin, cho đến nay không có đối tượng nào được trả lại, chỉ là một lỗi. Có thể bạn có cấu hình khác. Tôi tin rằng bạn có thể đặt nó để trả về một đối tượng (như một hình ảnh 404) nếu một đối tượng không tồn tại. –

+1

@AlvinK. bạn sai về điều này; SDK PHP của AWS tự động ném ngoại lệ khi nhận được phản hồi lỗi từ máy chủ - * không * chỉ vì lỗi kết nối. –

5

Tất cả các lỗi xảy ra trong các cuộc gọi đến các phương pháp của AWS SDK được chỉ định bằng cách ném ngoại lệ. Bạn có thể bắt những ngoại lệ nếu bạn muốn xử lý các lỗi.

Trong trường hợp đơn giản nhất, bạn có thể chỉ muốn bắt Exception:

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

Nếu bạn chỉ muốn xử lý ngoại lệ dự kiến ​​nhất định, tuy nhiên, trong khi cho phép người khác bong bóng lên và sụp đổ ứng dụng của bạn, sau đó mọi thứ trở nên một tinh tế hơn một chút.

Thứ nhất, mỗi một vài chục không gian tên trong AWS namespace chứa một không gian tên Exception trong đó nó định nghĩa các lớp ngoại lệ. Một trong các lớp này trong mỗi không gian tên là những gì mà Amazon gọi là lớp ngoại lệ dịch vụ mặc định cho không gian tên, từ đó tất cả các ngoại lệ khác được kế thừa. Ví dụ, S3 có Aws\S3\Exception namespaceS3Exception class. EC2 có Aws\Ec2\Exception namespaceEc2Exception class.

Lưu ý rằng việc bắt một trong những ngoại lệ này thay vì lớp cơ sở Exception ngay lập tức ngăn chúng tôi bắt lỗi nhất định! Các ngoại lệ dành riêng cho dịch vụ được đưa ra là kết quả của phản hồi lỗi từ máy chủ; ngoại lệ lỗi kết nối không được kế thừa từ chúng. Ví dụ, nếu bạn thử chạy đoạn mã sau không có kết nối internet ...

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

... thì ngoại lệ sẽ không bị bắt (vì nó sẽ là một Guzzle\Http\Exception\CurlException, không phải là một S3Exception) và chương trình sẽ tai nạn. Vì lý do này, nếu bạn đang bắt các ngoại lệ này chỉ để cung cấp thông báo lỗi chung cho người dùng, bạn có thể bắt được Exception.

Hãy quay lại câu hỏi về cách xử lý lỗi cụ thể. Đối với hầu hết các không gian tên, câu trả lời là sẽ có một lớp ngoại lệ được định nghĩa cho lỗi đó, và bạn nên nắm bắt điều đó. Ví dụ, giả sử chúng ta lại sử dụng phương thức S3 getObject và muốn làm điều gì đó khi nhóm chúng ta yêu cầu không tồn tại.Nhìn trong S3 Exception namespace docs, chúng ta thấy rằng có một NoSuchBucketException chúng ta có thể bắt:

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

(Trên thực tế, nó có thể cũng được dễ dàng hơn để tìm ra những trường hợp ngoại lệ có thể được ném bởi những gì hoạt động thông qua thử và sai hơn thông qua một cách cẩn thận đọc tài liệu.)

Cuối cùng, điều đáng nói đến là API EC2. Không giống như tất cả các dịch vụ khác, không gian tên EC2 chỉ bao gồm một lớp ngoại lệ duy nhất, Ec2Exception. Nếu bạn muốn nắm bắt và xử lý một lỗi cụ thể, bạn cần phải kiểm tra đối tượng ngoại lệ để tìm ra loại lỗi mà bạn đang xử lý. Bạn có thể làm điều này bằng cách kiểm tra giá trị trả về theo phương pháp getExceptionCode() của ngoại lệ.

Ví dụ, một (sửa đổi) đoạn mã từ một kịch bản gần đây tôi đã viết rằng trợ cấp quy định truy cập địa chỉ IP cho máy chủ MySQL của chúng tôi:

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; 
    } 
} 

Lưu ý rằng các mã ngoại lệ có thể - như InvalidPermission.Duplicate trong trường hợp này - không được liệt kê trong tài liệu SDK AWS PHP, nhưng bạn có thể tìm chúng bằng thử và sai hoặc từ documentation for the EC2 API itself, trong đó mỗi trang của hành động API chứa phần 'Lỗi' liệt kê các mã lỗi mà nó có thể trả về.

2

Bạn cũng có thể sử dụng phương pháp này: $response = $s3->doesObjectExist($bucket, $key);

Nó sẽ trả về một phản ứng đúng boolean nếu đối tượng tồn tại.

AWS Docs for doesObjectExist

+0

Tuyệt. Có phải mới không? –

+0

Chúng tôi đang may mắn, mã nguồn cho PHP aws sdk là trong github, tôi đã tìm hiểu và học API này đã được thêm vào bởi Michael Dowling vào ngày 12 tháng 7 năm 2012. Vì vậy, có nó tương đối mới, nó có thể đã được tung ra như một phần của bản phát hành cập nhật một thời gian sau đó. Tôi thích cách Amazon tiếp tục làm cho AWS tốt hơn! https://github.com/aws/aws-sdk-php/blame/master/src/Aws/S3/S3Client.php – Deemoe

+1

thật đáng buồn là không có trong amazon s3 v3 –