uniapp学习笔记——基于<uni-file-picker>组件和uni.uploadFile()方法实现图片上传

1、使用场景

  在编辑页面,有图片字段需要选择手机图片进行上传、预览、回显、删除等,尤其是当提交表单后,再次选择编辑该表单页面时,如何正确的显示图片,并保证再次提交时,可以没有异常。这里主要记录了一种在编辑表单时(图片字段返回的是图片地址)的一种处理方式,不一定是最佳实践,但是可以实现功能的正常使用。

2、组件用法简介

  组件和uni.uploadFile()方法在官方文档已经有非常详细的介绍了,这里只是简单说明一下,需要了解详细信息的请移步官方文档进行查看。

文件上传组件的用法

  文件选择上传组件,可以选择图片、视频等任意文件并上传到当前绑定的服务空间。

<uni-file-picker 
	v-model="imageValue" 
	fileMediatype="image" 
	mode="grid" 
	@select="select" 
	@progress="progress" 
	@success="success" 
	@fail="fail" 
/>
<script>
	export default {
		data() {
			return {
				imageValue:[]
			}
		},
		methods:{
			// 获取上传状态
			select(e){
				console.log('选择文件:',e)
			},
			// 获取上传进度
			progress(e){
				console.log('上传进度:',e)
			},
			
			// 上传成功
			success(e){
				console.log('上传成功')
			},
			
			// 上传失败
			fail(e){
				console.log('上传失败:',e)
			}
		}
	}
script>
文件上传方法uni.uploadFile(OBJECT)

  将本地资源上传到开发者服务器,客户端发起一个 POST 请求,其中 content-type 为 multipart/form-data。

uni.uploadFile({
	url: 'https://www.example.com/upload', //附件上传的服务器接口地址,非真实的接口地址
	filePath: tempFilePaths[0],//要上传文件资源的路径,不同的组件
	name: 'file',//文件对应的 key , 开发者在服务器端通过这个 key 可以获取到文件二进制内容,即附件信息的接收字段名称
	formData: {//HTTP 请求中其他额外的 form data	
		'user': 'test'
	},
	success: (uploadFileRes) => {//回调方法
		console.log(uploadFileRes.data);
	}
});

官方文档地址: 《文件上传组件用法》、《uni.uploadFile(OBJECT)方法使用方法》。

3、项目实践

  为了满足在前面提到的需求,我定义了一个变量isUploadImage,用于判断在编辑表单时,是否更新了图片。同时为了区分有时候需要上传附件,有时候不需要上传附件,把业务数据提交的方法抽离出了一个doSubmitData()方法。
  首先,当新增时,isUploadImage默认为true,即需要上传附件,这个时候添加附件后,调用doSubmit()时,实际上附件对象file变量为空,通过代码“this.$refs[‘files’].files[0];”获取上传的附件对象(这里其实可以通过监听组件的select或success实现赋值),然后再用uni.uploadFile()方法实现上传时,传入相关对象即可,当上传成功后,会返回图片的上传信息(不同附件上传接口不太一样,我这里返回了图片的名称,而且固定的前缀+图片名称,就可以实现图片的访问),然后把图片的名称再放到业务参数中和业务数据完成数据的提交。
  当编辑时,因为调用了查询详情,这个时候isUploadImage被设置为false,如果没有对图片做任何处理,数据提交时,将不会在提交图片,避免报错(这里应该有更加合理的实践,但是目前没有找到,而且如果没有修改避免再提交占用带宽也挺不错的注意),如果修改就需要删除图片,这个时候就会调用删除方法把isUploadImage设置为true,再次提交数据的时候,又会和新增的时候一样正常提交数据了。
  编辑时的回显,是:value=“imgPath”,并在加载详情的时候,为imgPath赋值实现的,这里的imgPath是一个对象,我为其中url属性赋值了,但是官方文档提示需要三个必填属性(不确定回显后,如果不删除直接上传会保存的问题是不是和这个有关系,未经验证):

  1. “name”:“file.txt”,
  2. “extname”:“txt”,
  3. “url”:“https://xxxx”,
<template>
	<view class="container">
		<uni-forms ref="formData" :modelValue="formData">
			<view class="context-section">
				<u-form-item label="图片附件" label-width="180">
					<uni-file-picker @delete="deleteImage" ref="files" :value="imgPath" file-mediatype="image" mode="grid" :limit="1"/>
					<view style="color: #c0c4cc">请上传图片,图片大小不超过20Mview>
				u-form-item>
				<view class="mt-3">
					<view style="text-align: center;" >
						<u-button class="btn" type="primary" size="medium" @click="doSubmit" >提交u-button>
					view>
				view>
			view>
		uni-forms>
	view>
template>

<script>
	import config from '@/config/config';
	export default {
		data() {
			return {
				file: null,
				imgPath: {},
				isUploadImage:true,//处理修改订单时,图片不修改的情况
				formData: {//业务数据,包括附件名称
					id: '',
					fileName: "",
					remark: ""
				}
			}
		},
		onLoad(option) {
			if (option && option.id) { //编辑页面,填充需要修改的数据
				this.getDetail(option.id);
				this.isUploadImage = false;
			}
		},
		
		methods: {
			getDetail(id) {
				this.$u.api.getDetail({
					id: id
				}).then(res => {
					if (res.success == 'true' || res.success) {
						this.formData = res.data
						if (this.formData && this.formData.fileName) {
							console.log(config.filePrefix + this.formData.fileName);
							this.imgPath = {
								'url': config.filePrefix + this.formData.fileName
							}
						}
					}
				});
			},
			deleteImage(e){
				console.log(e);
				this.imgPath = {};
				this.file = null;
				this.isUploadImage = true;//修改了图片允许图片上传
			},
			doSubmit() {
				this.$refs['formData'].validate().then(res => {
					uni.showLoading({
						title: '提交中...'
					});
					if(!this.isUploadImage){//不需要上传图片时
						this.doSubmitData();
						return;
					}
					if (!this.file) {
						if(this.$refs['files'].files.length > 0){
							this.file = this.$refs['files'].files[0];
						}
					}
					if(!this.file){
						console.log("没有附件信息!");
					}
					// 发送文件到后台
					uni.uploadFile({
						url: config.uploadUrl, // 后台接收文件的 API 地址
						filePath: this.file.path,
						name: 'file',
						header: {
							"Content-Type": "multipart/form-data",
						},
						success: (res) => {
							// 文件上传成功后的处理
							console.log(res.data);
							if(res.data){
								let reJson = JSON.parse(res.data);
								if(reJson && reJson.data && reJson.data.length>0){
									this.formData.fileName= reJson.data[0].fileName;
								}
							}
							this.doSubmitData();
						},
						fail: (err) => {
							uni.hideLoading()
							uni.showToast({
								title: '上传附件失败,请稍候再试!',
								duration: 1000,
								icon: 'none'
							});
							return;
						},
					});
				}).catch(err => {
					console.log(err);
					uni.showToast({
						title: "系统异常,错误信息:" + err,
						duration: 1000
					})
				})
			},
			doSubmitData(){//上传业务数据,包括图片地址
				console.log(this.formData);
				this.$u.api.doAdd(this.formData).then(res => {
					uni.hideLoading()
					if (res.success == 'true' || res.success) {
						uni.showToast({
							title: '创建成功!',
							duration: 1000,
							success: function() {
								uni.reLaunch({
									url: '/pages/index/index'
								})
							}
						})
					}
				});
			}
		}
	}
script>

<style lang="scss">

style>

你可能感兴趣的:(笔记,前端,uniapp,附件上传)