上传图片,压缩

上传事件的页面:

<template>
	<view>
		<view class="authState">
			<image src="/static/auth/auth-1.png" mode=""></image>
		</view>
		<view class="sfzInfo">
			<view class="title">请上传身份证的正反面</view>
			<view class="phoneCt">
				<view class="name">
					<view>头像面</view>
					<text>上传您的身份证头像面</text>
				</view>
				<view class="imgCt" @click="uploadImg('idCardFront')">
					<image v-if="!idCardFront" src="../../../static/auth/sfz-1.png" mode=""></image>
					<image v-else :src="'data:image/jpg;base64,'+ idCardFront" />
				</view>
			</view>
			<view class="phoneCt">
				<view class="name">
					<view>国徽面</view>
					<text>上传您的身份证国徽面</text>
				</view>
				<view class="imgCt" @click="uploadImg('idCardBack')">
					<image v-if="!idCardBack" src="../../../static/auth/sfz-2.png" mode=""></image>
					<image v-else :src="'data:image/jpg;base64,'+ idCardBack" />
				</view>
			</view>
			<view class="title">请完善您的个人信息</view>
			<view class="int">
				<view class="label">
					<view class="star">*</view>
					<view class="name">姓名:</view>
				</view>
				<uni-easyinput v-model="userName" borderBottom="5" class="int" textAlign="right" :inputBorder="false" placeholder="请输入姓名" clearable trim/>
			</view>
			<view class="int">
				<view class="label">
					<view class="star">*</view>
					<view class="name">身份证号:</view>
				</view>
				<uni-easyinput v-model="idCardNo" borderBottom="5" class="int" textAlign="right" :inputBorder="false" placeholder="请输入身份证号" clearable trim/>
			</view>
			<view class="btn" @click="stepToPage()">下一步</view>
		</view>
		<helang-compress ref="helangCompress"></helang-compress>
	</view>
</template>

<script>
	import {pathToBase64,base64ToPath} from '@/common/mmmm-image-tools/index.js'
	import helangCompress from '@/components/helang-compress/helang-compress';
	export default {
		components: {
		  helangCompress
		},
		data() {
			return {
				idCardFront:'',//身份证正面
				idCardBack:'',//身份证反面
				idCardNo:'',//身份证号码
				userName:'',//身份证名字
				isHaveInfo:false
			}
		},
		onLoad() {
		},
		methods: {
			uploadImg(type){
				let that = this
				uni.chooseImage({
					count: 1,
					sizeType: ['original', 'compressed'],
					// sourceType: ['album'], //从相册选择
					success: function (res) {
						that.setImg({path: res.tempFilePaths[0],dotype:type})
					}
				});
			},
			setImg(e){
				console.log(e)
				pathToBase64(e.path).then(base64 => {
					base64ToPath(base64).then(path => {
						//  压缩图片
						this.$refs.helangCompress.compress({
							src: path,
							maxSize: 800,
							fileType: 'jpg',
							quality: 0.85,
							minSize: 640 //最小压缩尺寸,图片尺寸小于该时值不压缩,非H5平台有效。若需要忽略该设置,可设置为一个极小的值,比如负数。
						}).then((pathImg) => {
							switch (e.dotype) {
								case 'idCardFront':
									this.idCardFrontReverse(pathImg)
									break;
								case 'idCardBack':
									this.idCardBackReverse(pathImg)
									break;
								default:
									uni.showToast({
										icon: 'none',
										title: '图片类型识别错误'
									})
							}
							// 压缩成功回调
						}).catch((err) => {
							console.log('压缩后失败', err)
						})
					})
				})
			},
			idCardFrontReverse(path){
				pathToBase64(path).then(base64 => {
					let url = "/checkImage";
					this.$u.post(url,{
						content: base64.split(',')[1],
						imageType: 'idcard'
					}).then(res => {
							this.idCardFront = base64.split(',')[1]
						  var ocr = JSON.parse(res.object)
						  this.userName = ocr.words_result['姓名'].words
						  this.idCardNo = ocr.words_result['公民身份号码'].words
					});
				})
			},
			idCardBackReverse(path) {
			  pathToBase64(path).then(base64 => {
			    this.idCardBack = base64.split(',')[1]
			  })
			},
			stepToPage(){
				this.$u.route('/pages/subpackage/auth/authXyk')
				const regex = /^(?:\d{15}|\d{17}[\dXx])$/;
				if (!this.idCardFront) {
					return this.$mytip.toast('请上传身份证人像面')
				}
				if (!this.idCardBack) {
					return this.$mytip.toast('请上传身份证国徽面')
				}
				if (!this.userName) {
					return this.$mytip.toast('请输入姓名')
				}
				if (!this.idCardNo) {
					return this.$mytip.toast('请输入身份证号码')
				}
				if (this.idCardNo.length !== 18) {
					return this.$mytip.toast('请输入正确对身份证号码')
				}
				if (!regex.test(this.idCardNo)) {
					return this.$mytip.toast('请输入正确的身份证号码')
				}
				const data = {
				  idCardBack: this.idCardBack,
				  idCardFront: this.idCardFront,
				  idCardNo: this.idCardNo,
				  userName: this.userName
				}
				let url = "/uploadIdCard";
				this.$u.post(url,data).then(res => {
						this.$mytip.toast('身份证上传成功')
						setTimeout(()=>{
							this.$u.route('/pages/subpackage/auth/authXyk')
						},1000)
				});
			}
		}
	}
</script>

<style lang="scss">
	page{
		background: #fff;
	}
	.authState{
		width: 100%;
		height: 116rpx;
		image{
			width: 100%;
			height: 116rpx;
		}
	}
	.sfzInfo{
		padding: 0 48rpx;
		.title{
			height: 80rpx;
			line-height: 80rpx;
			font-size: 32rpx;
			color:#1B1919;
			font-weight: 500;
		}
		.phoneCt{
			margin-bottom: 20rpx;
			padding: 40rpx 30rpx;
			display: flex;
			justify-content: space-between;
			width: 100%;
			background: #F4F6F8;
			.name{
				view{
					display: block;
					margin-bottom: 10rpx;
					font-size: 30rpx;
					color:#1B1919;
					font-weight: bold;
				}
				text{
					font-size: 28rpx;
					color:#666;
				}
			}
			.imgCt{
				width: 240rpx;
				height: 168rpx;
				image{
					width: 240rpx;
					height: 168rpx;
				}
			}
		}
		.int{
			display: flex;
			justify-content: left;
			align-items: center;
			height: 80rpx;
			line-height: 80rpx;
			border-bottom: 1rpx solid #eee;
			.label{
				width: 24%;
				display: flex;
				justify-content: left;
				align-items: center;
				.star{
					font-size: 28rpx;
					color:#D91616
				}
				.name{
					font-size: 28rpx;
					color:#1B1919;
				}
			}
			.icon{
				width: 40rpx;
				height: 40rpx;
				image{
					width: 40rpx;
					height: 40rpx;
				}
			}
		}
		.btn{
			margin: 60rpx auto 40rpx;
			width: 86%;
			height: 80rpx;
			line-height: 80rpx;
			font-size: 32rpx;
			color:#fff;
			text-align: center;
			background: linear-gradient( 90deg, #D91616 0%, #EE0808 100%);
			border-radius: 16rpx;
		}
	}
</style>

index.js 文件夹

function getLocalFilePath(path) {
    if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path.indexOf('_downloads') === 0) {
        return path
    }
    if (path.indexOf('file://') === 0) {
        return path
    }
    if (path.indexOf('/storage/emulated/0/') === 0) {
        return path
    }
    if (path.indexOf('/') === 0) {
        var localFilePath = plus.io.convertAbsoluteFileSystem(path)
        if (localFilePath !== path) {
            return localFilePath
        } else {
            path = path.substr(1)
        }
    }
    return '_www/' + path
}

function dataUrlToBase64(str) {
    var array = str.split(',')
    return array[array.length - 1]
}

var index = 0
function getNewFileId() {
    return Date.now() + String(index++)
}

function biggerThan(v1, v2) {
    var v1Array = v1.split('.')
    var v2Array = v2.split('.')
    var update = false
    for (var index = 0; index < v2Array.length; index++) {
        var diff = v1Array[index] - v2Array[index]
        if (diff !== 0) {
            update = diff > 0
            break
        }
    }
    return update
}

export function pathToBase64(path) {
    return new Promise(function(resolve, reject) {
        if (typeof window === 'object' && 'document' in window) {
            if (typeof FileReader === 'function') {
                var xhr = new XMLHttpRequest()
                xhr.open('GET', path, true)
                xhr.responseType = 'blob'
                xhr.onload = function() {
                    if (this.status === 200) {
                        let fileReader = new FileReader()
                        fileReader.onload = function(e) {
                            resolve(e.target.result)
                        }
                        fileReader.onerror = reject
                        fileReader.readAsDataURL(this.response)
                    }
                }
                xhr.onerror = reject
                xhr.send()
                return
            }
            var canvas = document.createElement('canvas')
            var c2x = canvas.getContext('2d')
            var img = new Image
            img.onload = function() {
                canvas.width = img.width
                canvas.height = img.height
                c2x.drawImage(img, 0, 0)
                resolve(canvas.toDataURL())
                canvas.height = canvas.width = 0
            }
            img.onerror = reject
            img.src = path
            return
        }
        if (typeof plus === 'object') {
            plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), function(entry) {
                entry.file(function(file) {
                    var fileReader = new plus.io.FileReader()
                    fileReader.onload = function(data) {
                        resolve(data.target.result)
                    }
                    fileReader.onerror = function(error) {
                        reject(error)
                    }
                    fileReader.readAsDataURL(file)
                }, function(error) {
                    reject(error)
                })
            }, function(error) {
                reject(error)
            })
            return
        }
        if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
            wx.getFileSystemManager().readFile({
                filePath: path,
                encoding: 'base64',
                success: function(res) {
                    resolve('data:image/png;base64,' + res.data)
                },
                fail: function(error) {
                    reject(error)
                }
            })
            return
        }
        reject(new Error('not support'))
    })
}

export function base64ToPath(base64) {
    return new Promise(function(resolve, reject) {
        if (typeof window === 'object' && 'document' in window) {
            base64 = base64.split(',')
            var type = base64[0].match(/:(.*?);/)[1]
            var str = atob(base64[1])
            var n = str.length
            var array = new Uint8Array(n)
            while (n--) {
                array[n] = str.charCodeAt(n)
            }
            return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { type: type })))
        }
        var extName = base64.split(',')[0].match(/data\:\S+\/(\S+);/)
        if (extName) {
            extName = extName[1]
        } else {
            reject(new Error('base64 error'))
        }
        var fileName = getNewFileId() + '.' + extName
        if (typeof plus === 'object') {
            var basePath = '_doc'
            var dirPath = 'uniapp_temp'
            var filePath = basePath + '/' + dirPath + '/' + fileName
            if (!biggerThan(plus.os.name === 'Android' ? '1.9.9.80627' : '1.9.9.80472', plus.runtime.innerVersion)) {
                plus.io.resolveLocalFileSystemURL(basePath, function(entry) {
                    entry.getDirectory(dirPath, {
                        create: true,
                        exclusive: false,
                    }, function(entry) {
                        entry.getFile(fileName, {
                            create: true,
                            exclusive: false,
                        }, function(entry) {
                            entry.createWriter(function(writer) {
                                writer.onwrite = function() {
                                    resolve(filePath)
                                }
                                writer.onerror = reject
                                writer.seek(0)
                                writer.writeAsBinary(dataUrlToBase64(base64))
                            }, reject)
                        }, reject)
                    }, reject)
                }, reject)
                return
            }
            var bitmap = new plus.nativeObj.Bitmap(fileName)
            bitmap.loadBase64Data(base64, function() {
                bitmap.save(filePath, {}, function() {
                    bitmap.clear()
                    resolve(filePath)
                }, function(error) {
                    bitmap.clear()
                    reject(error)
                })
            }, function(error) {
                bitmap.clear()
                reject(error)
            })
            return
        }
        if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
            var filePath = wx.env.USER_DATA_PATH + '/' + fileName
            wx.getFileSystemManager().writeFile({
                filePath: filePath,
                data: dataUrlToBase64(base64),
                encoding: 'base64',
                success: function() {
                    resolve(filePath)
                },
                fail: function(error) {
                    reject(error)
                }
            })
            return
        }
        reject(new Error('not support'))
    })
}

helang-compress.vue 文件

<template>
	<view class="compress" v-if="canvasId">
		<canvas :canvas-id="canvasId" :style="{ width: canvasSize.width,height: canvasSize.height}"></canvas>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				pic:'',
				canvasSize: {
					width: 0,
					height: 0
				},
				canvasId:""
			}
		},
		mounted() {
			if(!uni || !uni._helang_compress_canvas){
				uni._helang_compress_canvas = 1;
			}else{
				uni._helang_compress_canvas++;
			}
			this.canvasId = `compress-canvas${uni._helang_compress_canvas}`;
		},
		methods: {
			// 压缩
			compressFun(params) {
				return new Promise(async (resolve, reject) => {
					// 等待图片信息
					let info = await this.getImageInfo(params.src).then(info=>info).catch(()=>null);

					if(!info){
						reject('获取图片信息异常');
						return;
					}

					// 设置最大 & 最小 尺寸
					const maxSize = params.maxSize || 1080;
					const minSize = params.minSize || 640;

					// 当前图片尺寸
					let {width,height} = info;

					// 非 H5 平台进行最小尺寸校验
					// #ifndef H5
					if(width <= minSize && height <= minSize){
						resolve(params.src);
						return;
					}
					// #endif

					// 最大尺寸计算
					if (width > maxSize || height > maxSize) {
						if (width > height) {
							height = Math.floor(height / (width / maxSize));
							width = maxSize;
						} else {
							width = Math.floor(width / (height / maxSize));
							height = maxSize;
						}
					}

					// 设置画布尺寸
					this.$set(this,"canvasSize",{
						width: `${width}px`,
						height: `${height}px`
					});


					// Vue.nextTick 回调在 App 有异常,则使用 setTimeout 等待DOM更新
					setTimeout(() => {
						const ctx = uni.createCanvasContext(this.canvasId, this);
						ctx.clearRect(0,0,width, height)
						ctx.drawImage(info.path, 0, 0, width, height);
						ctx.draw(false, () => {
							uni.canvasToTempFilePath({
								x: 0,
								y: 0,
								width: width,
								height: height,
								destWidth: width,
								destHeight: height,
								canvasId: this.canvasId,
								fileType: params.fileType || 'png',
								quality: params.quality || 0.9,
								success: (res) => {
									// 在H5平台下,tempFilePath 为 base64
									resolve(res.tempFilePath);
								},
								fail:(err)=>{
									reject(null);
								}
							},this);
						});
					}, 300);
				});
			},
			// 获取图片信息
			getImageInfo(src){
				return new Promise((resolve, reject)=>{
					uni.getImageInfo({
						src,
						success: (info)=> {
							resolve(info);
						},
						fail: () => {
							reject(null);
						}
					});
				});
			},
			// 批量压缩
			compress(params){
				// index:进度,done:成功,fail:失败
				let [index,done,fail] = [0,0,0];
				// 压缩完成的路径集合
				let paths = [];
				// 待压缩的图片
				let waitList = [];
				if(typeof params.src == 'string'){
					waitList = [params.src];
				}else{
					waitList = params.src;
				}
				// 批量压缩方法
				let batch = ()=>{
					return new Promise((resolve, reject)=>{
						// 开始
						let start = async ()=>{
							// 等待图片压缩方法返回
							let path = await next().catch(()=>null);
							if(path){
								done++;
								paths.push(path);
							}else{
								fail++;
							}

							params.progress && params.progress({
								done,
								fail,
								count:waitList.length
							});

							index++;
							// 压缩完成
							if(index >= waitList.length){
								resolve(true);
							}else{
								start();
							}
						}
						start();
					});
				}
				// 依次调用压缩方法
				let next = ()=>{
					return this.compressFun({
						src:waitList[index],
						maxSize:params.maxSize,
						fileType:params.fileType,
						quality:params.quality,
						minSize:params.minSize
					})
				}

				// 全部压缩完成后调用
				return new Promise(async (resolve, reject)=>{
					// 批量压缩方法回调
					let res = await batch();
					if(res){
						if(typeof params.src == 'string'){
              // 为解决漏网之鱼,部分机型压缩不到的使用uni自带的压缩
              uni.getFileInfo({
                filePath:paths[0],
                success:imgInfo=>{
                  //console.log('这是uni压缩前的',imgInfo)
                  //  压缩完 如果还大于500Kb 则调用uni的方法再次压缩
                  if(imgInfo.size >= (500*1024)){
                    uni.compressImage({
                      src: paths[0],
                      quality: 10,
                      success: res => {
                        resolve(res.tempFilePath);
                      }
                    })
                  }else{
                    resolve(paths[0]);
                  }
                }
              })
						}else{
							resolve(paths);
						}
					}else{
						reject(null);
					}
				});
			}
		}
	}
</script>

<style lang="scss" scoped>
	.compress{
		position: fixed;
		width: 12px;
		height: 12px;
		overflow: hidden;
		top: -99999px;
		left: 0;
	}
</style>

效果如下图展示:上传头像面可自动识别出来姓名和身份证号

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值