美文网首页
php阿里云oss-sdk上传失败情况处理

php阿里云oss-sdk上传失败情况处理

作者: aiChenK | 来源:发表于2022-04-08 12:14 被阅读0次

    现象

    oss上传没有成功,但是拿到了地址,导致访问时返回404状态码

    思路

    我们先看自己写的上传oss部分代码

    public function oss(string $file, string $object)
    {
        $ossClient = new OssClient($this->config['accessKeyId'], $this->config['accessKeySecret'], $this->config['endpoint']);
        $result    = $ossClient->uploadFile($this->config['bucket'], ltrim($object, '/'), $file);
        return $result['oss-request-url'];
    }
    

    按理说是由sdk返回的result中拿到的地址,上传失败应该会直接抛出异常
    再看其中uploadFile代码部分

    public function uploadFile($bucket, $object, $file, $options = NULL)
    {
        // ...省略代码
        $response = $this->auth($options);
        $result = new PutSetDeleteResult($response);
        return $result->getData();
    }
    

    其中主要方法是$this->auth($options),再进去看

    private function auth($options)
    {
        // ...省略代码
    
        try {
            $request->send_request();
        } catch (RequestCore_Exception $e) {
            throw(new OssException('RequestCoreException: ' . $e->getMessage()));
        }
        $response_header = $request->get_response_header();
        $response_header['oss-request-url'] = $requestUrl;
        $response_header['oss-redirects'] = $this->redirects;
        $response_header['oss-stringtosign'] = $string_to_sign;
        $response_header['oss-requestheaders'] = $request->request_headers;
    
        $data = new ResponseCore($response_header, $request->get_response_body(), $request->get_response_code());
        //retry if OSS Internal Error
        if ((integer)$request->get_response_code() === 500) {
            if ($this->redirects <= $this->maxRetries) {
                //Sets the sleep time betwen each retry.
                $delay = (integer)(pow(4, $this->redirects) * 100000);
                usleep($delay);
                $this->redirects++;
                $data = $this->auth($options);
            }
        }
        
        $this->redirects = 0;
        return $data;
    }
    

    可以看到抛异常情况只在send_request方法,而里面只在curl本身无法请求(比如host无法解析)才会抛出RequestCore_Exception异常
    也就是说如果是业务类的错误是会正常走下去的
    虽然response_code为500时会有重试,但是在这之前已经创建了response对象
    如果非500错误,或者超过重试次数都会返回这个对象,最终情况就是不管怎么样都会返回result结构体

    解决

    在拿到result结构体后先进行response_code判断,代码如下

    public function oss(string $file, string $object)
    {
        $ossClient = new OssClient($this->config['accessKeyId'], $this->config['accessKeySecret'], $this->config['endpoint']);
        $result    = $ossClient->uploadFile($this->config['bucket'], ltrim($object, '/'), $file);
        if ($result['info']['http_code'] !== 200) {
            throw new OssException('上传失败');
        }
        return $result['oss-request-url'];
    }
    

    补充

    查阅了官方示例也没有对这些情况进行处理,示例如下:
    地址:https://help.aliyun.com/document_detail/88473.html

    // ...省略代码
    try{
        $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
    
        $ossClient->uploadFile($bucket, $object, $filePath);
    } catch(OssException $e) {
        printf(__FUNCTION__ . ": FAILED\n");
        printf($e->getMessage() . "\n");
        return;
    }
    print(__FUNCTION__ . "OK" . "\n");
    

    附上文档中其他错误码说明,文档链接:https://help.aliyun.com/document_detail/31978.html#section-orz-dlw-bz

    错误码 HTTP状态码 描述
    MissingContentLength 411 请求头没有采用chunked encoding编码方式,或没有设置Content-Length参数。
    InvalidEncryptionAlgorithmError 400 指定x-oss-server-side-encryption的值无效。取值:AES256、KMS或SM4。
    AccessDenied 403 添加Object时,用户对设置的Bucket没有访问权限。
    NoSuchBucket 404 添加Object时,设置的Bucket不存在。
    InvalidObjectName 400 传入的Object key长度大于1023字节。
    InvalidArgument 400 返回该错误的可能原因如下:添加的Object大小超过5 GB。x-oss-storage-class等参数的值无效。
    RequestTimeout 400 指定了Content-Length,但没有发送消息体,或者发送的消息体小于指定的大小。此种情况下服务器会一直等待,直至请求超时。
    Bad Request 400 在请求中指定Content-MD5后,OSS会计算所发送数据的MD5值,并与请求中Conent-MD5的值进行比较。如果二者不一致,则返回该错误。
    KmsServiceNotEnabled 403 x-oss-server-side-encryption指定为KMS,但没有预先购买KMS套件。
    FileAlreadyExists 409 当请求的Header中携带x-oss-forbid-overwrite=true时,表示禁止覆盖同名文件。如果同名文件已存在,则返回该错误。
    FileImmutable 409 Bucket中的数据处于被保护状态时,如果尝试删除或修改相应数据,则返回该错误。

    相关文章

      网友评论

          本文标题:php阿里云oss-sdk上传失败情况处理

          本文链接:https://www.haomeiwen.com/subject/rehysrtx.html