上传OSS直传
方式一:小程序端直接使用文件上传功能,获取上传的参数接口
配置依赖
composer require alibabacloud/credentials
<?php
require_once 'vendor/autoload.php';use AlibabaCloud\Credentials\Credential;// 设置bucket所处地域
$region = 'cn-hangzhou';
// 设置bucket名称
$bucket = 'bucketName';
$product = 'oss';// 创建阿里云凭证配置
$config = new Credential\Config([// 填写Credential类型,固定值为ecs_ram_role。'type' => 'ecs_ram_role',// 设置 ECS 实例的 RAM 角色名称'roleName' => "roleName",
]);
// 根据配置创建凭证对象
$credential = new Credential($config);
// 从凭证对象中获取凭证信息
$cred = $credential->getCredential();
// 获取当前的 UTC 时间
$utcTime = new DateTime('now', new DateTimeZone('UTC'));
// 格式化当前日期为 Ymd 格式,例如 20240101
$date = $utcTime->format('Ymd');
// 克隆当前时间对象,用于设置过期时间
$expiration = clone $utcTime;
// 设置过期时间为当前时间往后 1 小时
$expiration->add(new DateInterval('PT1H'));
// 构建policy
// 示例policy表单域只列举了部分必填字段,如有其他需求可参考签名版本4文档:https://help.aliyun.com/zh/oss/developer-reference/signature-version-4-recommend
$policyMap = ["expiration" => $expiration->format('Y-m-d\TH:i:s.000\Z'),"conditions" => [["bucket" => $bucket],["x-oss-signature-version" => "OSS4-HMAC-SHA256"],["x-oss-credential" => sprintf("%s/%s/%s/%s/aliyun_v4_request",$cred->getAccessKeyId(), $date, $region, $product)],["x-oss-date" => $utcTime->format('Ymd\THis\Z')],["x-oss-security-token" => $cred->getSecurityToken()],],
];
// 将policy转换为 JSON 格式的字符串
$policy = json_encode($policyMap);
// 对policy字符串进行 Base64 编码,得到待签名的字符串
$stringToSign = base64_encode($policy);
// 构建signingKey,由固定字符串 "aliyun_v4" 和访问密钥 Secret 拼接而成
$signingKey = "aliyun_v4" . $cred->getAccessKeySecret();
$h1Key = hmacSign($signingKey, $date);
$h2Key = hmacSign($h1Key, $region);
$h3Key = hmacSign($h2Key, $product);
$h4Key = hmacSign($h3Key, "aliyun_v4_request");// 使用 h4Key 对待签名的字符串进行 HMAC-SHA256 签名,得到最终的签名
$signature = hash_hmac('sha256', $stringToSign, $h4Key);// 构建响应给前端的表单数据,包含policy、签名版本、凭证、日期、签名和安全令牌等信息
echo json_encode(array('policy' => $stringToSign,"x_oss_signature_version" => "OSS4-HMAC-SHA256","x_oss_credential" => sprintf("%s/%s/%s/%s/aliyun_v4_request",$cred->getAccessKeyId(), $date, $region, $product),"x_oss_date" => $utcTime->format('Ymd\THis\Z'),"signature" => $signature,"security_token" => $cred->getSecurityToken()
));// hmacSign 函数,用于进行 HMAC-SHA256 签名计算
function hmacSign($key, $data)
{return hash_hmac('sha256', $data, $key, true);
}
方式二:小程序端使用OOS上传管理器,获取阿里云直传凭证STS Token
配置依赖
composer require alibabacloud/sdk
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\STS\STS;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;/*** 小程序端获取阿里云直传凭证STS Token*/public function getOssStstoken(){// 配置参数,建议在应用配置文件中设置$config = ['accessKeyId' => '', 'accessKeySecret' => '','bucket' => '','endpoint' => 'oss-cn-beijing.aliyuncs.com','regionId' => 'oss-cn-beijing','roleArn' => 'acs:ram::<你的阿里云账号ID>:role/<调用此接口的RAM角色名>','cdnurl' => 'https://你的域名',// 上传配置'maxSize' => 10485760, // 10MB'allowExt' => ['jpg', 'png', 'gif', 'jpeg', 'bmp'],'tokenExpireTime' => 3600, // 临时令牌有效期,单位秒,默认3600,最长可设置1小时];// 验证配置if (empty($config['accessKeyId']) || empty($config['accessKeySecret'])) {$this->error('阿里云配置不完整');}try {// 初始化阿里云客户端AlibabaCloud::accessKeyClient($config['accessKeyId'], $config['accessKeySecret'])->regionId($config['regionId'])->asDefaultClient();// 假设使用RAM角色获取临时令牌// 如果有RAM角色,使用AssumeRole方式if (!empty($config['roleArn'])) {$result = AlibabaCloud::rpc()->product('Sts')->version('2015-04-01')->action('AssumeRole')->method('POST')->scheme('https')->host('sts.aliyuncs.com')->options(['query' => ['RegionId' => $config['regionId'],'RoleArn' => $config['roleArn'],'RoleSessionName' => 'FastAdminApp','DurationSeconds' => $config['tokenExpireTime'],],])->request();$credentials = $result['Credentials'];} else {// 如果没有RAM角色,可以使用当前AccessKey(不推荐生产环境使用)exception('请配置RAM角色ARN');}// 返回令牌信息$data = ['accessKeyId' => $credentials['AccessKeyId'],'accessKeySecret' => $credentials['AccessKeySecret'],'securityToken' => $credentials['SecurityToken'],'expiration' => $credentials['Expiration'],'bucket' => $config['bucket'],'endpoint' => $config['endpoint'],'region' => $config['regionId']];} catch (ClientException $e) {$this->error('客户端错误: ' . $e->getErrorMessage());} catch (ServerException $e) {$this->error('服务端错误: ' . $e->getErrorMessage());} catch (\Exception $e) {$this->error('系统错误: ' . $e->getMessage());}$this->success('获取令牌成功', $data);}
