1、正常上传
<template> <div class="upload-wrapper"> <div v-if="!imgUrl" class="noneData"> <div @click="openLocals"> <img src="./imgs/icon_jh.png" alt=""> <div>上传图片</div> </div> <form :id="fileName+'Form'" enctype="multipart/form-data" style="display:none;"> <input ref="pathClear" type="file" accept="image/*" :name="fileName" @change="fileChanged"/> </form> </div> <div v-else class="havaData"> <img :src="imgUrl" alt="" @click="actImg"> </div> </div> </template> <script> import $ from 'jquery'; import { Indicator, Toast } from 'mint-ui'; import { webPostObject } from './ossUpload/index.js'; export default { data() { return { }; }, props: { // file控件名称 fileName: { type: String, required: true }, // 图片地址 imgUrl: { type: String, default: '', required: true }, }, methods: { // 点击图片 actImg() { console.log('点击图片'); }, // 删除图片 removePackage() { let _self = this; _self.$emit('removeImg'); }, // 上传图片 openLocals() { $(`input[type='file'][name='${this.fileName}']`).click(); }, fileChanged() { this.uploadImg(); }, uploadImg() { let _self = this; let fileElement = $(`input[type='file'][name='${_self.fileName}']`); let filename = fileElement.val(); let ext = filename.substring(filename.lastIndexOf('.')).toLowerCase(); if (ext !== '.jpg' && ext !== '.png' && ext !== '.jpeg' && ext !== '.bmp') { Toast({ message: '仅支持.jpg、.png、.jpeg、.bmp的图片格式', position: 'bottom', duration: 2000 }); return false; } let file = fileElement[0].files[0]; let imgSize = Math.ceil(file.size / 1024 / 1024); if (imgSize > 20) { Toast({ message: '文件不能大于20MB,重新选择文件', position: 'bottom', duration: 2000 }); _self.$refs.pathClear.value = ''; return false; } Indicator.open('图片正在上传中...'); // 服务器上传 // let formdata1 = new FormData(); // formdata1.append('file', file, file.name); // let config = { // headers: { 'Content-Type': 'multipart/form-data' } // }; // axios.post(`${process.env.UPLOAD_HOST}`, formdata1, config).then((res) => { // console.log(res); // let data = res.data; // Indicator.close(); // if (data) { // _self.$emit('uploadSuccess', data[0]); // } // }).catch(() => { // Indicator.close(); // Toast({ // message: '图片上传失败', // position: 'bottom', // duration: 2000 // }); // }); // oss web直传 webPostObject(file, file.name).then(data => { console.log('oss web直传', data); Indicator.close(); _self.$emit('uploadSuccess', data); }).catch(() => { Indicator.close(); Toast({ message: '图片上传失败', position: 'bottom', duration: 2000 }); }); }, }, }; </script> <style lang="less" scoped> .upload-wrapper{ height: 100%; } .noneData,.havaData{ position: relative; height: 100%; } .noneData{ background-color: #eeeeee; color: #999999; font-size: 12px; text-align: center; padding-top: 15px; img{ 26px; height: 26px; } } .havaData{ img{ 100%; height: 100%; } } </style>
2、压缩图片上传
<template> <div class="upload-wrapper"> <div v-if="!imgUrl" class="noneData"> <div class="uploadImg" @click="openLocals"> </div> <form :id="fileName+'Form'" enctype="multipart/form-data" style="display:none;"> <input ref="pathClear" type="file" accept="image/*" :name="fileName" @change="fileChanged"/> </form> </div> <div v-else class="havaData"> <div class="havaDataimg"> <div class="img_wap"> <img :src="imgUrl" alt="" @click.stop="bigPicture"> </div> <div class="remove" @click.stop="removePackage"></div> </div> </div> <div class="maxImg" @click="minImg" v-if="maxImg"> <img :src="imgUrl" alt=""> </div> </div> </template> <script> import $ from 'jquery'; import { Indicator, Toast } from 'mint-ui'; import axios from 'axios'; export default { data() { return { maxImg: false, xhr: null, ot: null, oloaded: null, }; }, props: { // file控件名称 fileName: { type: String, required: true }, // 图片地址 imgUrl: { type: String, default: '', required: true }, // 图片地址 isMaxIMg: { type: String, default: '', required: true }, }, methods: { // 查看大图 bigPicture() { console.log(this.isMaxIMg); if (this.isMaxIMg === '0') { return false; } this.maxImg = true; }, // 恢复小图 minImg() { this.maxImg = false; }, // 删除图片 removePackage() { let _self = this; _self.$emit('removeImg'); }, // 上传图片 openLocals() { $(`input[type='file'][name='${this.fileName}']`).click(); }, fileChanged() { this.UpladFile(); }, // 三个参数 // file:一个是文件(类型是图片格式), // w:一个是文件压缩的后宽度,宽度越小,字节越小 // objDiv:一个是容器或者回调函数 // photoCompress() photoCompress(file, w, objDiv) { let that = this; let ready = new FileReader(); // 开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容. ready.readAsDataURL(file); ready.onload = function() { let re = this.result; that.canvasDataURL(re, w, objDiv); }; }, canvasDataURL(path, obj, callback) { let img = new Image(); img.src = path; img.onload = function() { let that = this; // 默认按比例压缩 let w = that.width; let h = that.height; let scale = w / h; w = obj.width || w; h = obj.height || (w / scale); let quality = 0.7; // 默认图片质量为0.7 // 生成canvas let canvas = document.createElement('canvas'); let ctx = canvas.getContext('2d'); // 创建属性节点 let anw = document.createAttribute('width'); anw.nodeValue = w; let anh = document.createAttribute('height'); anh.nodeValue = h; canvas.setAttributeNode(anw); canvas.setAttributeNode(anh); ctx.drawImage(that, 0, 0, w, h); // 图像质量 if (obj.quality && obj.quality <= 1 && obj.quality > 0) { quality = obj.quality; } // quality值越小,所绘制出的图像越模糊 let base64 = canvas.toDataURL('image/jpeg', quality); // 回调函数返回base64的值 callback(base64); }; }, /** * 将以base64的图片url数据转换为Blob * @param urlData * 用url方式表示的base64图片数据 */ convertBase64UrlToBlob(urlData) { let arr = urlData.split(','); let mime = arr[0].match(/:(.*?);/)[1]; let bstr = atob(arr[1]); let n = bstr.length; let u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], { type: mime }); }, // 上传文件方法 UpladFile() { let that = this; let fileElement = $(`input[type='file'][name='${that.fileName}']`); let filename = fileElement.val(); let ext = filename.substring(filename.lastIndexOf('.')).toLowerCase(); if (ext !== '.jpg' && ext !== '.png' && ext !== '.jpeg' && ext !== '.bmp') { Toast({ message: '仅支持.jpg、.png、.jpeg、.bmp的图片格式', position: 'bottom', duration: 2000 }); return false; } let fileObj = fileElement[0].files[0]; let form = new FormData(); // FormData 对象 if (fileObj.size / 1024 > 1025) { // 大于1M,进行压缩上传 that.photoCompress(fileObj, { quality: 0.2 }, function(base64Codes) { let bl = that.convertBase64UrlToBlob(base64Codes); form.append('file', bl, 'file_' + Date.parse(new Date()) + '.jpg'); // 文件对象 let config = { headers: { 'Content-Type': 'multipart/form-data' } }; Indicator.open('图片正在上传中...'); axios.post(`${process.env.UPLOAD_HOST}`, form, config).then((res) => { console.log(res); let data = res.data; Indicator.close(); if (data) { that.$emit('uploadSuccess', data[0]); } }).catch(() => { Indicator.close(); Toast({ message: '图片过大上传失败', position: 'bottom', duration: 2000 }); }); }); } else { // 小于等于1M 原图上传 Indicator.open('图片正在上传中...'); form.append('file', fileObj); // 文件对象 axios.post(`${process.env.UPLOAD_HOST}`, form).then((res) => { console.log(res); let data = res.data; Indicator.close(); if (data) { that.$emit('uploadSuccess', data[0]); } }).catch(() => { Indicator.close(); Toast({ message: '图片过大上传失败', position: 'bottom', duration: 2000 }); }); } }, } }; </script> <style lang="less" scoped> .upload-wrapper{ position: relative; height: 172px; } .noneData,.havaData{ height: 100%; padding: 15px 16vw; position: relative; display: flex; justify-content: center; align-items: center; .uploadImg{ 102px; height: 102px; background-size: 100% 100%; background-image: url(./imgs/xh_pfgy_upload.png); } .havaDataimg{ position: relative; 100%; height: 100%; border: 1px solid #eeeeec; overflow: hidden; .img_wap{ 100%; height: 0px; padding-bottom: 56%; position: relative; img{ 100%; position: absolute; top: -30%; left: 0px; } } .remove{ position: absolute; top: 0; right: 0; 18px; height: 18px; background: url('./imgs/icon_close.png') rgba(255, 255, 255, 0.8) center center no-repeat; background-size: cover; border-radius: 50%; } } } // 大图效果 .maxImg{ position: fixed; top: 0px; left: 0px; right: 0px; bottom: 0px; overflow: auto; background-color:rgba(0, 0, 0, 0.5); z-index: 100; padding: 20px; display: flex; justify-content: center; align-items: center; img{ max- 100%; max-height: 100%; } } </style>
3、转为base64上传
<template> <div> <div style="padding:20px;"> <!-- <div class="show"> <div class="picture" :style="'backgroundImage:url('+headerImage+')'"></div> </div> --> <div class="havaDataimg"> <div class="img_wap"> <img :src="headerImage" alt=""> </div> <div class="remove"></div> </div> <div style="margin-top:20px;"> <input type="file" id="upload" accept="image/*" @change="upload"> <label for="upload"></label> </div> </div> </div> </template> <script> import Exif from 'exif-js'; import { Toast } from 'mint-ui'; export default { data() { return { headerImage: '', picValue: '' }; }, methods: { upload(e) { let files = e.target.files || e.dataTransfer.files; if (!files.length) return; this.picValue = files[0]; let filename = this.picValue.name; let ext = filename.substring(filename.lastIndexOf('.')).toLowerCase(); if (ext !== '.jpg' && ext !== '.png' && ext !== '.jpeg' && ext !== '.bmp') { Toast({ message: '仅支持.jpg、.png、.jpeg、.bmp的图片格式', position: 'bottom', duration: 2000 }); return false; } this.imgPreview(this.picValue); }, imgPreview(file) { let self = this; let Orientation; // 去获取拍照时的信息,解决拍出来的照片旋转问题 Exif.getData(file, function() { Orientation = Exif.getTag(this, 'Orientation'); }); // 看支持不支持FileReader if (!file || !window.FileReader) return; if (/^image/.test(file.type)) { // 创建一个reader let reader = new FileReader(); // 将图片2将转成 base64 格式 reader.readAsDataURL(file); // 读取成功后的回调 reader.onloadend = function () { let result = this.result; let img = new Image(); img.src = result; // 判断图片是否大于100K,是就直接上传,反之压缩图片 if (this.result.length <= (100 * 1024)) { self.headerImage = this.result; self.postImg(); } else { img.onload = function () { let data = self.compress(img, Orientation); self.headerImage = data; self.postImg(); }; } }; } }, postImg() { // 这里写接口 }, rotateImg(img, direction, canvas) { // 最小与最大旋转方向,图片旋转4次后回到原方向 const min_step = 0; const max_step = 3; if (img == null) return; // img的高度和宽度不能在img元素隐藏后获取,否则会出错 let height = img.height; let width = img.width; let step = 2; if (step == null) { step = min_step; } if (direction === 'right') { step++; // 旋转到原位置,即超过最大值 step > max_step && (step = min_step); } else { step--; step < min_step && (step = max_step); } // 旋转角度以弧度值为参数 let degree = step * 90 * Math.PI / 180; let ctx = canvas.getContext('2d'); switch (step) { case 0: canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0); break; case 1: canvas.width = height; canvas.height = width; ctx.rotate(degree); ctx.drawImage(img, 0, -height); break; case 2: canvas.width = width; canvas.height = height; ctx.rotate(degree); ctx.drawImage(img, -width, -height); break; case 3: canvas.width = height; canvas.height = width; ctx.rotate(degree); ctx.drawImage(img, -width, 0); break; } }, compress(img, Orientation) { let canvas = document.createElement('canvas'); let ctx = canvas.getContext('2d'); // 瓦片canvas let tCanvas = document.createElement('canvas'); let tctx = tCanvas.getContext('2d'); let initSize = img.src.length; let width = img.width; let height = img.height; // 如果图片大于四百万像素,计算压缩比并将大小压至400万以下 let ratio; if ((ratio = width * height / 4000000) > 1) { console.log('大于400万像素'); ratio = Math.sqrt(ratio); width /= ratio; height /= ratio; } else { ratio = 1; } canvas.width = width; canvas.height = height; // 铺底色 ctx.fillStyle = '#fff'; ctx.fillRect(0, 0, canvas.width, canvas.height); // 如果图片像素大于100万则使用瓦片绘制 let count; if ((count = width * height / 1000000) > 1) { console.log('超过100W像素'); count = ~~(Math.sqrt(count) + 1); // 计算要分成多少块瓦片 // 计算每块瓦片的宽和高 let nw = ~~(width / count); let nh = ~~(height / count); tCanvas.width = nw; tCanvas.height = nh; for (let i = 0; i < count; i++) { for (let j = 0; j < count; j++) { tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh); ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh); } } } else { ctx.drawImage(img, 0, 0, width, height); } // 修复ios上传图片的时候 被旋转的问题 if (Orientation !== '' && Orientation !== 1) { switch (Orientation) { case 6:// 需要顺时针(向左)90度旋转 this.rotateImg(img, 'left', canvas); break; case 8:// 需要逆时针(向右)90度旋转 this.rotateImg(img, 'right', canvas); break; case 3:// 需要180度旋转 this.rotateImg(img, 'right', canvas);// 转两次 this.rotateImg(img, 'right', canvas); break; } } // 进行最小压缩 let ndata = canvas.toDataURL('image/jpeg', 0.7); console.log('压缩前:' + initSize); console.log('压缩后:' + ndata.length); console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + '%'); tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0; return ndata; }, } }; </script> <style lang="less" scoped> *{ margin: 0; padding: 0; } /* .show { 100px; height: 100px; overflow: hidden; position: relative; border-radius: 50%; border: 1px solid #d5d5d5; } .picture { 100%; height: 100%; overflow: hidden; background-position: center center; background-repeat: no-repeat; background-size: cover; } */ .havaDataimg{ position: relative; 100%; height: 100%; border: 1px solid #eeeeec; overflow: hidden; .img_wap{ 100%; height: 0px; position: relative; padding-bottom: 56.25%; img{ 100%; position: absolute; top: -30%; left: 0px; } } } </style>
4引入组件使用
import uploadImg from '@/components/upload/prescriptionUploadImg'; components: { 'uploadImg': uploadImg, }, <uploadImg :imgUrl="pic_url" :fileName="'Image'" @uploadSuccess="addImgUrl" @removeImg="removeImgUrl"></uploadImg>