今天 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 ~