和大部分公有云一样,又拍云也有自己的签名上传机制。流程大概也是一样的,先从服务端获取签名授权,然后JS上传图片。也可以在控制台设置上传后的通知地址。不多说。直接上代码
服务器端(PHP laravel):
先安装又拍云SDK composer require upyun/sdk
use Upyun\Config;
use Upyun\Signature;
use Upyun\Util;
public function upYunPolicy(Request $request): JsonResponse
{
$validate = [
'folder' => ['required', Rule::in(['thumbs', 'qr_codes', 'certificate_attachments', 'article'])],
'type' => ['required', Rule::in(['image/jpeg', 'image/png'])],
'md5' => ['required', 'regex:/^[0-9a-z]{32}$/i'],
];
$this->validate($request, $validate);
$params = $request->only(array_keys($validate));
$config = new Config(env("YUN_BUCKET"), env("YUN_USER"), env("YUN_PWD"));
$config->setFormApiKey(env('YUM_SECRET'));
$path = "/{$params['folder']}/{$params['md5']}" . ('image/png' == $params['type'] ? '.png' : '.jpg');
$data['save-key'] = $path;//图片路径
$data['expiration'] = time() + 120;//签名有效时间,前端只能在此有效时间内使用签名
$data['bucket'] = env("YUN_BUCKET");//Bucket
$data['content-md5'] = $params['md5'];//文件Md5(非必填),如果此处填了下面getBodySignature生成签名的方法也要传入
$data['allow-file-type'] = 'jpg,png,jpeg';//限制上传文件类型
$data['content-length-range'] = '1024,1024000';//限制上传文件大小(1k-1M)
$policy = Util::base64Json($data);
$signature = Signature::getBodySignature($config, 'POST', '/' . env("YUN_BUCKET"), null, $policy, $params['md5']);
return $this->json([
'policy' => $policy,
'authorization' => $signature,
'url' => $config->getProtocol() . Config::ED_AUTO . '/' . env("YUN_BUCKET")
//上传URL从服务器返回,前端就不需要保存任何又拍云配置信息了
]);
}
前端(JS)
//acceptedFiles即为 File 元素 数组
acceptedFiles.forEach((file) => {
const reader = new FileReader();
reader.onload = function (event) {
var md5 = SparkMD5.hashBinary(event.target.result)
console.log("start upload file:" + md5);
//upload/policy 后端签名获取接口地址
axios.get("/upload/policy", {
params: {
folder: props.source, //文件夹
type: file.type,//文件类型
md5: md5//文件md5
}
}).then((response) => {
let params = new FormData();
params.append('file', file);
params.append('policy', response.policy)
params.append('authorization', response.authorization)
axios.post(response.url, params, {
headers: {'Content-Type': 'multipart/form-data'}
}).then((response) => {
console.log(response)
//上传成功回调
if (200 == response.code && response.url.length > 0) {
record[`${props.field}`] = response.url
}
})
}).catch((err) => {
if (err.status == 401) {
dispatch({type: "logout"})
} else {
notify(err.message)
}
})
}
reader.readAsBinaryString(file);
})