客户端直传步骤, oss后台配置好相关设置,可参考:https://help.aliyun.com/document_detail/92883.html 流程,服务端以PHP为例,
1.引入库
composer require ramsey/uuid //引入通用唯一识别ID
2.此处是服务端获取阿里签名代码
<?php
namespace app\service;
use Ramsey\Uuid\Uuid;
/**
* Class AliOssService
* @package app\service
*
* 微信小程序直传实践
* @see https://help.aliyun.com/document_detail/92883.html
*/
class AliOssService
{
// 配置oss参数
private const AccessKeyId = '<AccessKeyId>';
private const AccessKeySecret = '<AccessKeySecret>';
private const Host = 'https://<region>.oss-cn-beijing.aliyuncs.com';
// 签名有效期 单位: 秒
private const Expire = 3 * 60;
// 允许上传的文件最大和最小范围 单位:字节
private const ContentLengthMin = 0;
private const ContentLengthMax = 20 * 1024 * 1024;
/**
* 获取服务端签名方式上传参数
* @param $params array
* ext string 扩展名 eg: jpg
* dirname string 上传目录 eg: image
* @return array
* @throws \Exception
*/
public static function getUploadParams($params)
{
// 接收参数
$ext = $params['ext'];
$dirname = $params['dirname'];
// 文件路径和文件名
$dir = self::getDirname($dirname);
$key = $dir . self::getFilename($ext);
// 过期时间
$expiration = self::getExpireTime(self::Expire);
// 参数设置
// 附录:Post Policy
// https://help.aliyun.com/document_detail/31988.htm#section-d5z-1ww-wdb
$policyParams = [
'expiration' => $expiration,
'conditions' => [
// 指定前缀
['starts-with', '$key', $dir],
// 限制上传文件大小。单位:字节
['content-length-range', self::ContentLengthMin, self::ContentLengthMax]
]
];
$policyBase64 = self::getPolicyBase64($policyParams);
$signature = self::getSignature($policyBase64, self::AccessKeySecret);
return [
'accessKeyId' => self::AccessKeyId,
'host' => self::Host,
'policy' => $policyBase64,
'signature' => $signature,
'expire' => $expiration,
'key' => $key,
'url' => self::Host . '/' . $key
];
}
/**
* 获取参数base64
* @param $policyParams array
* @return string
*/
public static function getPolicyBase64($policyParams)
{
return base64_encode(json_encode($policyParams));
}
/**
* 获取签名
* @param $policyBase64 string
* @param $accessKeySecret string
* @return string
*/
public static function getSignature($policyBase64, $accessKeySecret)
{
return base64_encode(hash_hmac('sha1', $policyBase64, $accessKeySecret, true));
}
/**
* 获取过期时间
* @param $time int 单位: 秒
* @return mixed
*/
public static function getExpireTime($time)
{
return str_replace('+00:00', '.000Z', gmdate('c', time() + $time));
}
/**
* 获取按照月份分隔的文件夹路径
* @param $dirname string eg: image/video
* @return string eg: image/2022-10/
*/
public static function getDirname($dirname)
{
return $dirname . '/' . date('Y-m') . '/';
}
/**
* 获取一个随机的文件名
* @param $ext string eg: jpg
* @return string eg: a4030d9f-c4a2-4f1a-8e33-80e017e572d5.jpg
* @throws \Exception
*/
public static function getFilename($ext)
{
$uuid = Uuid::uuid4()->toString();
return $uuid . '.' . $ext;
}
}
3.提供给客户端获取签名的接口实现
<?php
namespace app\controller;
use app\BaseController;
use app\exception\AppException;
use app\service\AliOssService;
class AliOssController extends BaseController
{
public function getUploadParams()
{
$ext = input('ext');
$dirname = input('dirname', 'image');
// 参数校验
if (!$ext) {
throw new AppException('ext is empty');
}
if (!in_array($dirname, ['image', 'video'], true)) {
throw new AppException('dirname: only allow image or video');
}
$result = AliOssService::getUploadParams([
'ext' => $ext,
'dirname' => $dirname,
]);
return $result;
}
}
4.客户端直传实战,以微信小程序侧代码示例,获取到服务端签名,然后直传阿里oss
// 获取文件扩展名
function getFilePathExtention(filePath) {
return filePath.split('.').slice(-1)[0];
}
// 上传到阿里云oss
function uploadFileAsync(config, filePath) {
console.log(config);
return new Promise((resolve, reject) => {
wx.uploadFile({
url: config.host, // 开发者服务器的URL。
filePath: filePath,
name: 'file', // 必须填file。
formData: {
key: config.key,
policy: config.policy,
OSSAccessKeyId: config.accessKeyId,
signature: config.signature,
// 'x-oss-security-token': securityToken // 使用STS签名时必传。
},
success: (res) => {
console.log(res);
if (res.statusCode === 204) {
resolve();
} else {
reject('上传失败');
}
},
fail: (err) => {
// console.log(err);
reject(err);
},
});
});
}
// 上传文件
export async function uploadFile(filePath, dirname = 'image') {
console.log(filePath);
let ext = getFilePathExtention(filePath);
// 改方法通过接口获取服务端生成的上传签名
const resParams = await Http.AliOssGetUploadParams({
ext,
dirname,
});
// console.log(resParams.data);
// let objectName = resParams.data.uuid + '.' + getFilePathExtention(filePath);
await uploadFileAsync(resParams.data, filePath);
// console.log(res);
return resParams;
}
© 版权声明
文章版权归作者所有,转载请注明出处。
THE END
暂无评论内容