uni-app+uview: uni.chooseImage选择相册/拍照后使用u-upload进行上传

5,375 阅读2分钟

我的需求是做一个类似朋友圈一样选择图片并能实时预览和删除的场景,图片在点击发布时和其他内容一起保存到数据库,一开始的想法是一次性传过去后返回一组图片url直接上传,但是自己渲染的照片没有删除和预览大图功能,发现u-upload组件已经整合了我所需要的功能,所以获取图片以后就直接使用组件内部的方法进行上传。

注意:我这边后端接口接收类型为form-data,参数名为files,数组

html部分 这里我自定义了一个上传图片的按钮可以直接调用uni.chooseImage的方法,没有使用upload自带的,所以需要对组件的上传按钮进行隐藏,也可以使用组件自带的上传按钮,但需要设置一个方法拦截其自带的上传(return false)然后在catch中调用chooseImage

<view class="choose-box">
	<view v-if="imgNum < 9" class="choose-img" @click="chooseImg">
        <u-icon name="plus" size="40" color="#C2C7CC"></u-icon>
    </view>
</view>
 
<!--关闭自动上传功能-->
 
<u-upload ref="uUpload" name="files" :header="myHeader" :action="uploadUrl" :auto-upload="false" :show-tips="false"></u-upload>

css部分

.choose-box {
	height: 150rpx;
}
 
.choose-img {
	display: flex;
	align-items: center;
	justify-content: center;
	margin-left: 20rpx;
	margin-top: 40rpx;
	width: 150rpx;
	height: 150rpx;
	border-radius: 4rpx;
	background-color: rgba(255, 255, 255, 100);
	text-align: center;
	border: 2rpx dashed rgba(194, 199, 204, 100);
}
 
/deep/ .u-add-wrap {
	display: none;
}
 
//让预览图片的列表一列显示三个并设置为我需要的尺寸
/deep/ .u-list-item {
	width: 220rpx !important;
	height: 150rpx !important;
}
/deep/ .u-upload {
	justify-content: space-between;
	&::after {
		content: '';
		width: 220rpx;
		height: 150rpx;
	}
}

data部分

data() {
		return {
			     imgNum: 0,
                 form:{imgList:[]}
                };
	},
    computed: {
		uploadUrl() {
			return `上传地址`;
		},
		myHeader() {
           //写入自己token的位置
			return { Authorization: uni.getStorageSync('TOKEN') };
		}
	},

method部分(上传图片)

chooseImg() {
	uni.chooseImage({
	count: 9,
        sizeType: ['original', 'compressed'],
	sourceType: ['camera', 'album'],
	success: res => {
		const { tempFilePaths, tempFiles } = res;
                //获取图片的数据插入到upload中
 
		if (this.imgNum === 9) {
		uni.showToast({
                title: '超过最大数量',
                duration: 2000,
                icon: 'error'
                     });
                } else {
                //循环插入到upload的list中
                tempFilePaths.forEach((item, index) => {
					this.$refs.uUpload.lists.push({
                                        error: false,
                                        file: tempFiles[index],
                                        progress: 0,
                                        url: item
                                        });
                                  });
                                  
                this.$refs.uUpload.upload();//调用手动上传方法
                this.imgNum = this.$refs.uUpload.lists.length;//当前图片数量
                }
           }
       });
}

补充失败的处理

  fail: (err) => {
          uni.getSetting({
            success: (res) => {
              let authStatus = res.authSetting['scope.camera'];
              if (!authStatus) {
                uni.showModal({
                  title: '授权失败',
                  content: 'Hello uni-app需要从您的相机获取视频,请在设置界面打开相关权限',
                  success: (res) => {
                    if (res.confirm) {
                      uni.openSetting()
                    }
                  }
                })
              }
            }
          })
        }

最后在保存/发布的代码中插入这么一段方法将目前列表中上传成功的图片返回的数据获取到,就不需要手动去写保存返回数据和删除的方法了,代码如下,方法参考官方文档

// 通过filter,筛选出上传进度为100的文件(因为某些上传失败的文件,进度值不为100,这个是可选的操作)	        
let files = [];
 
files = this.$refs.uUpload.lists.filter(val => {
		return val.progress == 100;
});
 
// 如果不需要进行太多的处理,直接如下即可
// files = this.$refs.uUpload.lists;
files = this.$refs.uUpload.lists.map(i => {
		if (i.response) {
			return i.response.data.imgList[0];//因为我这边返回的是一个数组,所以需要加索引
			} else {
			return i.url;//这里是用于有预置的图片fileList的情况,如果没有可去掉
			}
        });
 
//最后得到需要传给后端的图片url
this.form.imgList = files;

最后效果如图 image.png