OSS 直传阿里腾讯示例

caylof

今天 Q 群有朋友说不会 OSS 直传,那我就来写个例子吧。欢迎兄弟们探讨交流。

0. 引入 aws 的 sdk

composer require aws/aws-sdk-php

1. 上传到阿里云OSS

1.1 创建S3客户端

$s3client = new \Aws\S3\S3Client([
    'credentials' => [
        'key'    => 'KEY',
        'secret' => 'SK',
    ],
    'region' => 'oss-cn-chengdu',
    'version' => '2006-03-01',
    'endpoint' => 'https://caylof.oss-cn-chengdu.aliyuncs.com',
    'use_path_style_endpoint' => true,
//    'endpoint' => 'https://oss-cn-chengdu.aliyuncs.com',
//    'addressing_style' => 'virtual',
]);

1.2 服务器上传文件

通常前端先上传到服务器,然后通过服务器再上传到OSS,即中传了一次。

function put(\Aws\S3\S3Client $s3client): void
{
    $bucket = 'a';
    $key = '123.txt';

    $s3client->putObject([
        'Bucket' => $bucket,
        'Key' => $key,
        'Body' => file_get_contents(__DIR__.'/1.php'),
        'ContentType' => 'text/plain',
    ]);
}

1.3 前端直传文件到OSS

1.3.1 服务器先生成签名表单

function buildForm(\Aws\S3\S3Client $s3client): array
{
    $bucket = 'a/123.txt'; // 这里阿云的兼容似乎有点别扭,用真正的bucket会有问题
    $key = 'a/123.txt';

    $maxUploadSize = 1024 * 1024 * 10;
    $contentType = 'text/plain';

    $formInputs = ['acl' => 'private'];
    $options = [
        ['acl' => 'private'],
        ['bucket' => $bucket],
        ['key' => $key],
        ['Content-Type' => $contentType],
        ['content-length-range', 1, $maxUploadSize],
    ];
    $expires = '+10 minutes';
    $postObject = new \Aws\S3\PostObjectV4(
        $s3client,
        $bucket,
        $formInputs,
        $options,
        $expires
    );

    $formAttributes = $postObject->getFormAttributes();
    $formInputs = $postObject->getFormInputs();
    $formInputs['key'] = $key;
    $formInputs['Content-Type'] = $contentType;

//    print_r($formAttributes);
//    print_r($formInputs);

    return [$formAttributes, $formInputs];
}

返回的 $formAttributes$formAttributes 就是前端需要的表单属性和表单输入,然后用于前端进行构造表单并提交即可。

1.3.2 前端直接上传文件

我这里不采用JS(通常会是axios)来构造表单,而是用 PHP 的 guzzle client 来模拟前端实现。

function uploadMock(array $formAttributes, array $formInputs): void
{
    $multipart = [];
    foreach ($formInputs as $name => $value) {
        $multipart[] = [
            'name' => $name,
            'contents' => $value,
        ];
    }
    $multipart[] = [
        'name' => 'file',
        'contents' => file_get_contents(__DIR__.'/1.php'),
    ];

    $http = new \GuzzleHttp\Client();
    $resp = $http->put($formAttributes['action'], [
        'multipart' => $multipart,
        'headers' => [
            'Accept' => 'application/json',
        ],
    ]);
    echo $resp->getStatusCode() . PHP_EOL;
    print_r($resp->getBody()->getContents());
}

2. 上传到腾讯云COS

2.1 创建S3客户端

$s3client = new \Aws\S3\S3Client([
    'credentials' => [
        'key'    => 'KEY',
        'secret' => 'SK',
    ],
    'region' => 'auto',
    'version' => 'latest',
    'endpoint' => 'https://xxx-yyy.cos.ap-chengdu.myqcloud.com',
    'use_path_style_endpoint' => true,
]);

服务器上传文件同上阿里云。

2.2 前端直接上传文件

2.2.1 服务器先生成签名表单

function buildForm(\Aws\S3\S3Client $s3client): array
{
    $bucket = 'xxx-yyy'; // 这里腾讯云看起来比阿里云做的合理
    $key = 'a/123.txt';

    $maxUploadSize = 1024 * 1024 * 10;
    $contentType = 'text/plain';

    $formInputs = ['acl' => 'private'];
    $options = [
        ['acl' => 'private'],
        ['bucket' => $bucket],
        ['key' => $key],
        ['Content-Type' => $contentType],
        ['content-length-range', 1, $maxUploadSize],
    ];
    $expires = '+10 minutes';
    $postObject = new \Aws\S3\PostObjectV4(
        $s3client,
        $bucket,
        $formInputs,
        $options,
        $expires
    );

    $formAttributes = $postObject->getFormAttributes();
    $formInputs = $postObject->getFormInputs();
    $formInputs['key'] = $key;
    $formInputs['Content-Type'] = $contentType;

//    print_r($formAttributes);
//    print_r($formInputs);

    return [$formAttributes, $formInputs];
}

2.2.2 前端直接上传文件

function uploadMock(array $formAttributes, array $formInputs): void
{
    $multipart = [];
    foreach ($formInputs as $name => $value) {
        $multipart[] = [
            'name' => str_replace('X-Amz', 'X-Cos', $name), // 腾讯云对名称做了替换处理,一个小细节
            'contents' => $value,
        ];
    }
    $multipart[] = [
        'name' => 'file',
        'contents' => file_get_contents(__DIR__.'/1.php'),
    ];

    $http = new \GuzzleHttp\Client();
    $resp = $http->put($formAttributes['action'], [
        'multipart' => $multipart,
        'headers' => [
            'Accept' => 'application/json',
        ],
    ]);
    echo $resp->getStatusCode() . PHP_EOL;
    print_r($resp->getBody()->getContents());
}

~ over ~

382 1 1
1个评论

timeless-zyg

aws不是亚马逊的包吗?

  • 北月 24天前

    国内的云存储厂商基本上都支持 AWS S3 对象存储协议,S3 成为了云存储事实上的标准。

caylof

340
积分
0
获赞数
0
粉丝数
2022-08-13 加入
×
🔝