有很长一段时间没有更新了,由于工作的繁忙导致没有时间写博客,今天在做到公司特殊场景需要用到上传组件并直传阿里云Oss,这里简单讲讲我在完成前端项目中使用到Uview的Upload遇到的问题以及我是如何解决,直传阿里云Oss的。
uview-ui: "^2.0.31"
node:14.18.1
https://www.uviewui.com/components/upload.html
这里如果你单纯的想拿到上传之后的url的话,可以直接看官方实例:
<script>
export default {
data() {
return {
fileList1: [],
}
},
methods:{
// 删除图片
deletePic(event) {
this[`fileList${event.name}`].splice(event.index, 1)
},
// 新增图片
async afterRead(event) {
// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
let lists = [].concat(event.file)
let fileListLen = this[`fileList${event.name}`].length
lists.map((item) => {
this[`fileList${event.name}`].push({
...item,
status: 'uploading',
message: '上传中'
})
})
for (let i = 0; i < lists.length; i++) {
const result = await this.uploadFilePromise(lists[i].url)
let item = this[`fileList${event.name}`][fileListLen]
this[`fileList${event.name}`].splice(fileListLen, 1, Object.assign(item, {
status: 'success',
message: '',
url: result
}))
fileListLen++
}
},
uploadFilePromise(url) {
return new Promise((resolve, reject) => {
let a = uni.uploadFile({
url: 'http://192.168.2.21:7001/upload', // 仅为示例,非真实的接口地址
filePath: url,
name: 'file',
formData: {
user: 'test'
},
success: (res) => {
setTimeout(() => {
resolve(res.data.data)
}, 1000)
}
});
})
},
}
}
</script>
这里的:fileList=fileList1
要与data中的fileList1
一一对应,不能乱写,具体原因可以继续看下去。
他其实本质是对uniapp的upload的再次封装!
我们使用这个组件上传后,我们可以打印出返回的event
这里是结果,
如果是单图上传,我们可以发现,我们的图片存储在了一个对象里,里面的file中有我们图片的名称,大小,以及临时存储路径,如果你传给后端只需要传链接,那么看这里就可以结束了,剩下的就是格式的问题,看后端需要什么样的图片格式,对blob流进行相应的转化即可,
这里属于是特殊的场景需求了,有需要的小伙伴可以看下去。
如果改造Uview的Upload来进行前端直传阿里云Oss
我们仔细观察官方实例,其实可以发现,上传的核心代码是在这里:
const result = await this.uploadFilePromise(lists[i].url)
uploadFilePromise(url) {
return new Promise((resolve, reject) => {
let a = uni.uploadFile({
url: 'http://192.168.2.21:7001/upload', // 仅为示例,非真实的接口地址
filePath: url,
name: 'file',
formData: {
user: 'test'
},
success: (res) => {
setTimeout(() => {
resolve(res.data.data)
}, 1000)
}
});
})
},
通过循环遍历图片数组,将图片调用uploadFilePromise
方法进行上传,我们拿到图片的临时url,使用uni.uploadFile
方法进行上传图片,所以他其实本质是对uni的上传方法进行二次封装,那么清楚原理之后,我们进行改造,要直传阿里云Oss,首先我们得获得阿里云Oss的权限,这里一般情况都是通过后端拿到临时阿里云Oss访问权限,也就是我们所说的密钥
。
https://help.aliyun.com/document_detail/111265.html?spm=a2c4g.11186623.0.0.6f6d110aTbK5Vs
最重要的其实就是这两个,访问阿里云Oss,当然还有其他很多的参数,这个看具体的业务场景需求,可能还需要其他的参数,但是密钥是必须的,所以要想上传阿里云Oss,就得先获得权限,下面会解释遇到的坑。
accessid:密钥ID
signature:密钥
policy
我们改造官方示例:
let a = uni.uploadFile({
url: your.host, // 仅为示例,非真实的接口地址,这里的地址是传阿里云oss的地址
filePath: url, //url就是你拿到的图片url,这里不用动
fileType: type, //类型 ,这里是必填的,直接拿event里面的type即可
name: 'file', //不用动
formData: {
key: this.key, //这里是指你存放到阿里云oss的路径
region: 'oss-cn-shenzhen', //这里是阿里云需要的地域
policy: this.oss.policy, //签名
signature: this.oss.signature, //密钥
OSSAccessKeyId: this.oss.accessid, //id
},
success: (res) => {
// setTimeout(() => {
// resolve(res.data.data)
// }, 1000)
resolve(res.data.data)
//成功的回调
}
我们发现,虽然返回的是uploadFile:ok,但是Oss中并没有,我们仔细看,其实还是失败的,是errMsg,这种一般是权限问题,可以跟后端沟通配合解决,报错中也会提示究竟是哪个权限有问题。
跨域的问题在浏览器中经常会有,这个网上的配置有很多,你可以参考一下,当然,最简单无脑的方式,你可以直接使用HbuilderX的内置浏览器,当然体验不是特别好,但是没有跨域的问题!
我在使用官方示例没有问题,但当我使用多个Upload进行上传就出现了问题,找不到fileList
后来我发现了,官方实例中的这一句
let fileListLen = this[`fileList${event.name}`].length
这是Es6的模板字符串,跟我一样看不懂的,属实得多看看基础了
this[`fileList${event.name}`]
他其实是这个this.fileList+event.name
所以,注意:我们的upload中的name
和:fileList="xxx"
,不能自己去乱定义,你使用官方的示例,那就得遵守规则,这个name的值,其实就是event.name的值,如果你的name为“1”,那么:fileList="fileList1"
就必须得这么写
同理可得:
<u-upload
:fileList="fileList1"
@afterRead="afterRead"
@delete="deletePic"
name="1"
multiple
:maxCount="10"
></u-upload>
<u-upload
:fileList="fileList2"
@afterRead="afterRead"
@delete="deletePic"
name="2"
multiple
:maxCount="10"
></u-upload>
<u-upload
:fileList="fileList3"
@afterRead="afterRead"
@delete="deletePic"
name="3"
multiple
:maxCount="10"
></u-upload>
data() {
return {
fileList1: [],
fileList2: [],
fileList3: [],
}
你就得这么写,所以一开始使用为什么觉得这么命名那么奇怪,想自定义命名的同学们,那就得体验一下报错的快感了。
我是前端小白,如果你觉得这篇文章有哪些不足之后,或者还遇到什么奇怪的问题,可以在评论区留言