当前位置: 欣欣网 > 码农

对象存储OSS直传阿里云腾讯云示例

2024-07-17码农

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

引入 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,即中传了一次。

functionput(\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 服务器先生成签名表单

functionbuildForm(\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 来模拟前端实现。

functionuploadMock(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 服务器先生成签名表单

functionbuildForm(\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 前端直接上传文件

functionuploadMock(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 ~