在项目里有时候会碰到比如上传文件相关的,一般都是后端提供个接口,然后我们上传的时候后端再传到阿里OSS或者其他服务商的对象存储,然后把最终的url
拿到存起来或者返回给前端,这种方式其实在上传图片的频率不高的业务场景中可能并无大碍,但是如果有频繁的上传文件的场景,服务器压力较大,那就要介绍一种解决方法,前端直传ali-oss。
1.ali-oss npm包
提供了非常多的api,可自行到www.npmjs.com/package/ali... 查看
2.介绍前端直传file的几种方式
put
特点
- 适用于小文件和普通文件上传。
- 使用
put
方法上传文件时,整个文件会一次性上传到 OSS,如果文件较小(通常小于 100MB),那么这种方式是最简单和高效的。 - 如果上传的文件较大(通常大于 100MB),使用
put
方法可能会导致网络不稳定或服务器超时,因此不适合大文件上传,可能会出现上传失败或上传时间过长的情况。
参数
:一般接收两个参数, 文件路径
文件file`
引入ali-oss
bash
#安装
npm install ali-oss --save
需要实例化oss
javascript
import OSS from "ali-oss"
或通过cdn的方式引入
php
const client = new OSS({
// 将<your_bucket>设置为OSS Bucket名称。
bucket: "<your_bucket>",
//oss中项目的accessKeyId 和 accessKeySecret
accessKeyId: credentials.AccessKeyId,
accessKeySecret: credentials.AccessKeySecret,
//从STS服务获取的安全令牌(SecurityToken)
stsToken: credentials.SecurityToken,
secure: true, //是否启用HTTPS,https true http false
endpoint: 'oss-cn-hangzhou.aliyuncs.com' ,//地域节点 ==》外网访问
// 将<your_region>设置为OSS Bucket所在地域,例如region: 'oss-cn-hangzhou'。
region: "oss-cn-hangzhou",
});
如何获取accessKeyId 和 accessKeySecret
1、点击概览 --- AccessKey
oss控制台官网链接:oss.console.aliyun.com/overview
2、出现下图,选择开始使用子用户Access Key
3、填写用户名,并点击确定
4、这时会给你的手机发送验证码确认是否是本人操作,填写验证码后,用户创建成功
5、创建完毕后,会出现下面的页面,我们可以看到创建的accessKeyId
、AccessKeySecret
6、为新创建的用户添加权限
OSS官网也提供了一份关于put去上传文件的demo
xml
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>上传文件到OSS</title>
<script src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.17.0.min.js"></script>
</head>
<body>
<div class="container">
<form>
<div class="mb-3">
<label for="file" class="form-label">选择文件</label>
<input
type="file"
class="form-control"
id="file"
name="file"
required
/>
</div>
<button type="submit" class="btn btn-primary">上传</button>
</form>
</div>
<script type="text/javascript">
let credentials = null;
const form = document.querySelector("form");
form.addEventListener("submit", async (event) => {
event.preventDefault();
try {
// 临时凭证过期时,才重新获取,减少对 sts 服务的调用
if (isCredentialsExpired(credentials)) {
const response = await fetch("/get_sts_token_for_oss_upload", {
method: "GET",
});
if (!response.ok) {
throw new Error("无法获取STS临时凭证");
}
credentials = await response.json();
}
const client = new OSS({
// 将<your_bucket>设置为OSS Bucket名称。
bucket: "<your_bucket>",
// 将<your_region>设置为OSS Bucket所在地域,例如region: 'oss-cn-hangzhou'。
region: "oss-<your_region>",
accessKeyId: credentials.AccessKeyId,
accessKeySecret: credentials.AccessKeySecret,
stsToken: credentials.SecurityToken,
});
const fileInput = document.querySelector("#file");
const file = fileInput.files[0];
const result = await client.put(file.name, file);
console.log(result);
alert("文件已上传");
} catch (error) {
console.error(error);
if (error.code === "Forbidden" || error.code === 403) {
alert("缺少OSS操作权限");
} else {
alert("存在跨域问题,请确认OSS Bucket正确配置了CORS。");
}
}
});
/**
* 判断临时凭证是否到期。
**/
function isCredentialsExpired(credentials) {
if (!credentials) {
return true;
}
const expireDate = new Date(credentials.Expiration);
const now = new Date();
// 如果有效期不足一分钟,视为过期。
return expireDate.getTime() - now.getTime() <= 60000;
}
</script>
</body>
</html>
multipartUpload
特点
:
- 适用于大文件和断点续传。
- 使用
multipartUpload
方法时,文件会被分割成多个部分(即分片),每个分片独立上传到 OSS,并在 OSS 上重新组装成完整的文件。 - 分片上传可以提高上传效率,避免网络不稳定或服务器超时导致的上传失败,同时也支持断点续传,即使网络中断或上传过程中出现其他问题,也可以在中断处继续上传。
参数
: 1. 文件的完整上传路径 1.文件
可以看出回调中提供了一些关于进度等属性
我也写了一个简单的demo作为参考
实例化oss
javascript
import OSS from 'ali-oss';
export const client = new OSS({
accessKeyId: 'xxxxx', //访问键ID
accessKeySecret: 'xxxxxx', //访问密钥
bucket: 'a-bucket', //桶名
secure: true, //是否启用HTTPS,https true http false
endpoint: 'oss-cn-beijing.aliyuncs.com' //地域节点 ==》外网访问
// region : 'oss-cn-beijing' // 就是外网访问的区域去掉.aliyuncs.com
})
upload
javascript
upload(file, loading = true) {
// 上传的文件名称
const uuid = nanoid();
const index = file.name.lastIndexOf(".")
// 截取文件的后缀
const suffix = file.name.substring(index + 1)
// 二级目录名称
const currentDate = tool.dateFormat(new Date(), 'yyyy-MM-dd')
// 完整的上传路径 第一级路径/第二级路径/文件名 这个看不同的公司给定
let fileName = "第一级路径/" + 第二级路径 + "/" + uuid + "." + suffix //定义唯一的文件名,打印出来的uid其实就是时间戳
try{
const data = await client.multipartUpload(fileName,file,{
progress:function(percent){
console.log("上传进度",percent)
}
})
}catch(error){
ElMessage.error("上传失败")
}
},