【关于我接触了Uview的Upload】——单图上传,多图上传,遇到的问题总结、直传阿里云Oss

Uview的Upload组件

前言

有很长一段时间没有更新了,由于工作的繁忙导致没有时间写博客,今天在做到公司特殊场景需要用到上传组件并直传阿里云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流进行相应的转化即可,

如果是多图上传,那么file会有多个对象,也是同样的道理。
在这里插入图片描述

直传阿里云oss

这里属于是特殊的场景需求了,有需要的小伙伴可以看下去。
如果改造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访问权限,也就是我们所说的密钥

阿里云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,出现的问题

我在使用官方示例没有问题,但当我使用多个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: [],
			}

你就得这么写,所以一开始使用为什么觉得这么命名那么奇怪,想自定义命名的同学们,那就得体验一下报错的快感了。

后言

我是前端小白,如果你觉得这篇文章有哪些不足之后,或者还遇到什么奇怪的问题,可以在评论区留言

猜你喜欢

转载自blog.csdn.net/m0_46983722/article/details/128119584