uniapp原生图片上传组件
需求:文件上传速度快,但是拉取图片的速度慢,前台要实现了断点续存功能。
优化:前台在上传文件时会获得一个本地的临时路径,在填写人第一次上传表单并且没有退出时使用本地临时路径展示给用户查看;若用户退出了表单填写,数据会放松给后台存储到数据库,后端返回一个缩略图,前端默认展示后端给的缩略图,在用户预览图片时再去拉取后端的高清图,实现图片上传优化。
1、模板
<view class="cont">
<view class="title">
<view class="label-name">
<text>相关图片:</text>
</view>
</view>
<view class="info">
<view v-if="上传操作">
<view class="img_box">
<view
v-for="(item, index) in imageUrlFiles"
:key="index"
>
<view class="images-box">
<image
class="img"
:src="item.imgUrl"
mode="aspectFill"
@click="previewImg(index,$event)"
></image>
<view class="img-del" @click="imgDelete(item,index,$event)">
<u-icon name="close" color="#999" size="18"></u-icon>
</view>
<u-loading-icon class="loading" text="上传中" color="#5cadff" textColor="#5cadff" vertical textSize="18" :show="item.isShowUploadingImg"></u-loading-icon>
</view>
</view>
<view
id="img"
class="img-box"
v-if="form.imageFiles.length < 8"
@click="addPic"
>
<u-icon name="camera" color="#999" size="30"></u-icon>
</view>
</view>
</view>
<view v-else>//后续展示图片
<view class="static_img_box" v-if="form.imageFiles.length > 0">
<view v-for="(item,index) in form.imageFiles" :key="index">
<view class="static_images-box">
<image :src="item.imgUrl" mode="aspectFill" @click="previewImg(index,$event)"></image>
</view>
</view>
</view>
<view v-else>
无
</view>
</view>
</view>
</view>
2、样式
.cont {
display: flex;
}
.cont .title{
width: 130px;
margin-right: 10px;
}
.cont .info {
flex: 1;
}
.cont .title .label-name {
width: 130px;
display: flex;
flex-direction: row;
// 微信的flex盒子的justify-content align-items要使用flex-end
justify-content: flex-end;
align-items: center;
margin-right: 10px;
}
.img_box {
width: 100%;
display: flex;
flex-wrap: wrap;
}
.img_box .images-box {
position: relative;
width: 80px;
height: 80px;
margin: 5px;
}
.img_box .images-box image
{
width: 100%;
height: 100%;
}
.loading {
position: absolute;
background-color: #f5f5f5;
z-index: 100;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.img_box .images-box .img-del {
position: absolute;
top: 0;
right: 0;
z-index: 100;
}
.img_box .img-box {
width: 80px;
height: 80px;
box-sizing: border-box;
margin: 5px;
display: flex;
justify-content: center;
}
.static_img_box {
width: 100%;
display: flex;
flex-wrap: wrap;
}
.static_img_box .static_images-box {
width: 80px;
height: 80px;
margin: 5px;
}
.static_img_box .static_images-box image{
width: 100%;
height: 100%;
}
3、逻辑
async addPic(e) {
const _this = this;
uni.chooseImage({
count: 8, //最多数量
sizeType: ['compressed'],
sourceType: ['album', 'camera'],
success: function(res) {
let flag = true
res.tempFiles.forEach(item => {
console.log(item.name.includes('.tiff'))
if(!(item.name.includes('.tiff') || item.name.includes('.pjp') || item.name.includes('.jfif')
|| item.name.includes('.bmp') || item.name.includes('.gif') || item.name.includes('.svg')
|| item.name.includes('.png') || item.name.includes('.xbm') || item.name.includes('.jpeg')
|| item.name.includes('.jpg') || item.name.includes('.webp') || item.name.includes('.tif')
|| item.name.includes('.pjpeg') || item.name.includes('.avif') || item.name.includes('.svgz')
|| item.name.includes('.dib') || item.name.includes('.jxl') || item.name.includes('.ico'))){
uni.$u.toast('请选择正确的图片格式')
flag = false
return
}
if(item.size > 10485760){
uni.$u.toast('上传图片大小不能超过10MB');
flag = false
return
}
})
if(flag){
// res.tempFilePaths是前端图片上传后的临时路径
_this.handleUploadFile(res.tempFilePaths);
}
}
});
},
//上传图片,还要对接接口
async handleUploadFile(data) {
const _this = this;
let obj ={
imgUrl: data[0],//这个是缩略图
isShowUploadingImg : false
}
this.imageUrlFiles.push(obj)
this.imageUrlFiles[this.imageUrlFiles.length - 1].isShowUploadingImg = true
let guid = data[0].substring(data[0].lastIndexOf('/') + 1)
const filePath = data.path || data[0];
await uni.uploadFile({
//仅为示例,非真实的接口地址
url: this.$constDefinition.baseUrl + '/file/UploadByUnacceptedOrder',
filePath: filePath,
name: 'file',
//此处还要加一个值,后端需要前台传递的参数
formData: {
id: _this.form.id,
type: _this.type,
guid: guid
},
success: uploadFileRes => {
console.log('uploadFileRes',uploadFileRes)
const uploaddata = JSON.parse(uploadFileRes.data);
var imgUrl = this.$constDefinition.baseUrl + uploaddata.result.imageUrl;
_this.form.imageFiles.push(imgUrl)
},
complete: () => {
_this.imageUrlFiles[_this.imageUrlFiles.length - 1].isShowUploadingImg = false
}
});
},
//预览图片
previewImg(index,e) {
let perviewFile = []
this.imageUrlFiles.forEach(item => {
// 后端给的是缩略图,前端自己改变图片地址,拿到高清图
item = item.imgUrl.replace('previewThumbnail','preview')
console.log(item)
perviewFile.push(item)
})
uni.previewImage({
urls: perviewFile,
current: index, //这个属性可以确定点击的是第几张图片
longPressActions: {
itemList: ['发送给朋友', '保存图片', '收藏'],
success: function(data) {
},
fail: function(err) {
// console.log(err.errMsg);
}
}
});
},
//删除图片
imgDelete(item, index,e) {
let _this = this
uni.showModal({
// title: '您确定要删除吗?',
content:'您确定要删除吗?',
success: async (res) => {
if(res.confirm){
item = item.imgUrl.substring(item.imgUrl.lastIndexOf('/') + 1)
//后端删除接口
const response = await _this.$ajax(`/api/services/app/ComFile/DeleteFileByGuid?guid=${item}`, {}, 'delete');
if(response.success == false){
uni.showToast({
title: response.error.message,
duration: 1500,
icon:'error',
mask: true
})
return
}
// 实现前端页面删除
_this.imageUrlFiles.splice(index,1)
} else if(res.cancel){}
}
})
},