基于VUE的图片上传

很久没写东西了,因为懒

Posted by 昆山吴彦祖 on 2020.08.28

最近客户写的一个 案子, 需要一个前端比较复杂的步奏型下单功能,然后就稍微看了下 VUE,拿来用了
不得不说,VUE 对于后端工程师还是很友好的,用 api和更多以往后端语言的特性(可能是我不太熟js)来操作前端,这里记录一个 vue + 图片上传


<div class="form-group" id="vue">
<label for="exampleInputPassword1">原始CAD图纸-上传进度({{imgTempList.length}}/5)</label>
<div>
	<div class="uploading-data" v-if="isUploading"></div>
	
	<div class="upload-img-column">
	
	<div class="upload-wrap">
	<div class="box">
		<label class="p dotted">
		<input type="file" accept="image/jpg,image/jpeg,image/png" name="file" @change="onChooseImage($event)" />
		<img src="images/jiahao.png" alt="">
		</label>
	</div>
	
	<template v-for="(imgItem, imgIndex) in imgTempList">
		<div class="box">
		<div class="p">
		<img :src="imgItem">
		<div class="delete" @click.stop="deleteImg(imgIndex)">
		<img src="images/guanbi.png" alt="">
		</div>
		</div>
		</div>
	</template>
	</div>
	
	</div>

	<div class="success-path">
		<template v-for="(item, index) in successPath">
		<a :href="base+item" target="_blank">{{item}}</a>
		</template>
	</div>
</div>

<div class="invalid-feedback" v-show="errors.file">
{{errors.file?errors.file[0]:''}}
</div>
</div>


var v1 = new Vue({
	el: '#vue',
	data: {
	
		imgTempList: [], //图片临时路径列表
		isUploading: false, //是否正在上传
		successPath: [], //上传成功后的路径(没必要)
		base:'/uploads/',
		},
	methods: {
		//选择图片
		onChooseImage: function (event) {
			var that = this;

			//判断图片数量是否已上限
			var currentImgTempArray = that.imgTempList;
			if (currentImgTempArray.length >= 5) {
				alert("最多上传5张图片");
				return false;
			}

			//使用FileReader对文件对象进行操作
			var reader = new FileReader();
			reader.readAsDataURL(event.target.files[0]); //将读取到的文件编码成Data URL
			reader.onload = function () { //读取完成时
				var replaceSrc = reader.result; //文件输出的内容


				//调用图片压缩处理方法
				that.compressedImage({
					src: replaceSrc,
					quality: 0.8,
					success: function (src) {
						//将压缩后的路径 追加到临时路径数组中
						var totalList = [];
						if (currentImgTempArray.length > 0) {
							totalList = currentImgTempArray.concat(src);
						} else {
							totalList[0] = src;
						}
						that.imgTempList = totalList;
						that.onUploadImg(src)
					}
				});
			};

		},

		//删除某张图片
		deleteImg: function (idx) {
			var that = this;
			that.imgTempList.splice(idx, 1);
		},


		//提交上传图片
		onUploadImg: function (src) {
			var that = this;
			that.isUploading = true; //正在上传 显示遮罩层 防止连续点击

			var files = that.dataURLtoFile(src, 'pj' + Date.now() + '.jpg'); //DataURL转File

			//创FormData对象
			var formdata = new FormData();
			//append(key,value)在数据末尾追加数据。 这儿的key值需要和后台定义保持一致
			formdata.append('img', files);

			//用axios上传,
			axios({
				method: "POST",
                                //图片上传接口,返回图片存储地址
				url: "/api/upload_image/upload",
				data: formdata,
				headers: {
					"Content-Type": "multipart/form-data"
				}
			}).then(function (res) {
				console.log(res.data)
				
				that.isUploading = false;
				
				that.successPath.push(res.data);
				
				console.log(that.successPath)

			}).catch(function (error) {
				console.error(error);
			});
		},

		/**
		 * 压缩图片处理
		 * @src 需要压缩的图片base64路径
		 * @quality 图片质量 0-1,默认1
		 * @success()  成功后的回调
		 * */
		compressedImage: function (params) {
			var that = this;

			var initParams = {
				src: params.src || "",
				quality: params.quality || 1,
			};

			var image = new Image();
			image.src = initParams.src;
			image.onload = function () {
				//获取图片初始宽高
				var width = image.width;
				var height = image.height;
				//判断图片宽度,再按比例设置宽度和高度的值
				if (width > 1920) {
					width = 1920;
					height = Math.ceil(1920 * (image.height / image.width));
				}

				//将图片重新画入canvas中
				var canvas = document.getElementById("compressCanvas");
				if(!canvas){ //如果没有压缩用的canvas 就创建一个canvas画布
					var body = document.body;
					canvas = document.createElement("canvas"); //创建canvas标签
					canvas.id = "compressCanvas"; //给外层容器添加一个id
					canvas.style.position = "fixed";
					canvas.style.zIndex = "-1";
					canvas.style.opacity = "0";
					canvas.style.top = "-100%";
					canvas.style.left = "-100%";
					body.append(canvas);
				}

				var context = canvas.getContext("2d");
				canvas.width = width;
				canvas.height = height;
				context.beginPath();
				context.fillStyle = "#ffffff";
				context.fillRect(0, 0, width, height);
				context.fill();
				context.closePath();
				context.drawImage(image, 0, 0, width, height);
				var replaceSrc = canvas.toDataURL("image/jpeg", initParams.quality); //canvas转DataURL(base64格式)

				params.success && params.success(replaceSrc);
			};
		},

		/**
		 * 将base64转换为文件
		 * @dataUrl base64路径地址
		 * @fileName 自定义文件名字
		 * */
		dataURLtoFile: function (dataUrl, fileName) {
			var arr = dataUrl.split(','), mime = arr[0].match(/:(.*?);/)[1],
				bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
			while (n--) {
				u8arr[n] = bstr.charCodeAt(n);
			}
			return new File([u8arr], fileName, {type: mime});
		},
	}
})