uniapp-H5端使用uni.uploadFile上传图片或图像,文件没有后缀名,导致图片上传失败的解决办法

1、先说问题吧

我最近写了一个小程序,有一个拍照上传图片的功能,用Uview的u-upload组件写的,在小程序端测试一切功能正常,但是到H5端就发现图片没法传给后端或者传过去的图片后端无法识别,报500错误

原始代码

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: this.baseUrl + '/common/upload',
						filePath: url,  
						name: 'file',  
						formData: {}, 
						header: {  
						  Authorization: 'Bearer ' + getToken(), 
						 'Content-Type': 'multipart/form-data' 
						},  
						success: (res) => {
							this.lastList.push(JSON.parse(res.data).fileName)
							this.files=this.lastList.join(',')
							setTimeout(() => {
								resolve(res.data.data)
							}, 1000)
						}
					});
				})
			},

后台调试发现的问题

这里看似数据上传成功了,但是

发现后端并没有给返回数据,还来了个500,正常来说此时应该请教后端大佬的,但是这个地方比较特殊,问题在于前端传过去的数据有问题,但是这个不怪我们,而是uniapp官方背大锅,h5端与其他小程序、app在这个地方的处理方式不同,上面的方法其他端通用,唯独h5不行,请看vcr

uni.uploadFile(OBJECT) | uni-app官网

问题就在这里,h5端上传前必须转为file对象上传,其他端直接filePath就ok;

2、解决办法(超级大招)

代码放下边了,具体的改动就是我上面图片画红框的地方

整体流程思路:

        1、基本上传的图片无非就是base64编码或者blob对象或者"blob:https://localhost:9090/2a68b651-7a69-48c8-9998-a9bdde15f52a"

        2、无论是上面哪种情况,直接将base64转file或者blob转file

        大多数应该是blob这种情况,下面也有示例代码,大家对照着抄就完事了

// 新增图片
			async afterRead(event) {
				// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
				let lists = [].concat(event.file)
				console.log(lists)
				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++) {
				// 将blob转为file对象的方法
				function blobToFile(blob,fileName){
					return new File([blob],fileName,{type:'image/png'})
				}
				// 获取blob对象
				fetch(lists[i].url)
					.then(response=>response.blob())
					.then(blob=>{
						// 将blob转换为file
						let fileN = blobToFile(blob,lists[i].name)
						// 上传file对象
						this.uploadFilePromise(fileN)
							.then(result=>{
								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) {
				// console.log(fileN)
				return new Promise((resolve, reject) => {
					let a = uni.uploadFile({
						url: this.baseUrl + '/common/upload',
						file: url,  
						name: 'file',  
						formData: {}, 
						fileType:"image",
						header: {  
						  Authorization: 'Bearer ' + getToken(), 
						 // 'Content-Type': 'multipart/form-data' 
						},  
						success: (res) => {
							console.log(res)
							this.lastList.push(JSON.parse(res.data).fileName)
							this.files=this.lastList.join(',')
							console.log(this.files)
							setTimeout(() => {
								resolve(res.data.data)
							}, 500)
						}
					});
				})
			},

有个地方忘说了,就是文件后缀名丢失的问题

接两张图给大家看一下,打印的内容分别是最开始没改代码时分别在小程序端、h5端运行打印lists[i]的结果

小程序:

h5端

对比就发现后缀少了,而官方给的解决办法就是我上面说的,上传file对象,不能直接给个filePath了。

使用 Vue 或 UniApp 开发应用时,可以利用 uni-app 的 API uni.chooseImage 和 uni.uploadFile 来实现图片的上传和更换。下面是具体的实现步骤和代码示例: 1. 使用 uni.chooseImage 选择图片: 该方法可以弹出图片选择器,用户可以选择本地相册中的图片,或者使用相机拍摄新图片。选择图片后,会返回图片的本地文件路径。 ```javascript uni.chooseImage({ count: 1, // 默认选择1张图片 sizeType: ['compressed'], // 可以指定选择大图还是小图 sourceType: ['album', 'camera'], // 可以选择相册或相机 success: (res) => { // 处理用户选择的图片 const tempFilePaths = res.tempFilePaths; // 将图片路径保存,以便上传 this.selectedImage = tempFilePaths[0]; }, fail: (err) => { // 处理错误情况 console.error(err); } }); ``` 2. 使用 uni.uploadFile 上传图片: 得到图片的本地文件路径后,使用 uni.uploadFile 方法将图片上传到服务器。该方法会返回一个上传任务 ID,可以通过这个 ID 监听上传进度和上传成功后的状态。 ```javascript uni.uploadFile({ url: '服务器上传接口', // 上传图片到服务器的接口地址 filePath: this.selectedImage, // 本地图片路径 name: 'file', // 上传时的文件名 success: (uploadRes) => { // 上传成功的回调函数 const data = JSON.parse(uploadRes.data); // 处理返回的数据,比如更新UI显示上传成功的图片等 console.log('上传结果', data); }, fail: (err) => { // 上传失败的回调函数 console.error('上传失败', err); } }); ``` 请注意,上传图片到服务器通常需要处理跨域问题,确保服务器设置允许来自客户的请求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值