使用element ui的Upload 上传组件,实现图片压缩

在template中代码

					<el-form-item 
                            label="图片"
                            :label-width="'120px'"
                            prop="menuName"
                  >
					<el-upload
                                action="#"
                                class="avatar-uploader"
                                :auto-upload="false"
                                :show-file-list="false"
                                :on-success="handleAvatarSuccess"
                                :before-upload="beforeAvatarUpload"
                                :on-change="onChange"
                            >
                                <img v-if="imageUrl" :src="imageUrl" class="avatar">
                                <i v-else class="el-icon-plus avatar-uploader-icon"></i>
                            </el-upload>
                        </el-form-item>

script中代码

<script>
// 引入做压缩处理的函数
import { 
    transitionBase64,
    compressImg,
    dataURItoBlob,
    base64ToFile
 } from '@/utils/compressTransitionImg.js'
export default {
    data() {
        return {
            imageUrl: '',
        }
    },
    methods: {
        // 图片改变
        async onChange(file, fileList) {
            console.log('file, fileList', file, fileList)
            console.log('上传的文件file', file)
            const isJPG = file.type === 'image/jpeg';
            const isLt2M = file.size / 1024 / 1024 < 2;

            /* if (!isJPG) {
                this.$message.error('上传头像图片只能是 JPG 格式!');
            }
            if (!isLt2M) {
                this.$message.error('上传头像图片大小不能超过 2MB!');
            } */

            // 定义需要上传的文件
            let formData = new FormData()
            formData.append('file', file.raw)
            console.log('formData', formData)
            console.log('formData.getAll()', formData.getAll(['file']))
            
            // this.imageUrl = URL.createObjectURL(file.raw)

            let result = await transitionBase64(file.raw)
            let compressImgResult = await compressImg(result, 50 * 1024)
            // console.log(111, result)
            console.log('压缩后的文件', compressImgResult)
            console.log('压缩后的文件转blob', dataURItoBlob(compressImgResult))
            console.log('压缩后的文件转file对象', base64ToFile(compressImgResult, file.name.split('.')[0]))

            // this.imageUrl = URL.createObjectURL(dataURItoBlob(compressImgResult))
            // 显示压缩后的图片
            this.imageUrl = URL.createObjectURL(base64ToFile(compressImgResult, file.name))

        },
        


        // 以下方法无用
        handleAvatarSuccess(res, file) {
            this.imageUrl = URL.createObjectURL(file.raw);
        },
        beforeAvatarUpload(file) {
            console.log('上传的文件file', file)
            const isJPG = file.type === 'image/jpeg';
            const isLt2M = file.size / 1024 / 1024 < 2;

            if (!isJPG) {
                this.$message.error('上传头像图片只能是 JPG 格式!');
            }
            if (!isLt2M) {
                this.$message.error('上传头像图片大小不能超过 2MB!');
            }
            return true;
            return isJPG && isLt2M;
        },
        handleRemove(file) {
            console.log(file);
        },
        handlePictureCardPreview(file) {
            this.dialogImageUrl = file.url;
            this.dialogVisible = true;
        },
        handleDownload(file) {
            console.log(file);
        }
    }
}
</script>

新建compressTransitionImg.js封装压缩图片函数

// 
// 封装上传图片时的压缩方法及其base64转bolb
// 将bolb转换成base64
export function transitionBase64(blob) {
    return new Promise((resolve, reject) => {
        // 创建一个FileReader实例
        const reader = new FileReader();
        let base64String
        // 设置FileReader的onload事件处理程序,当转换完成时调用
        reader.onload = function(event) {
            // 事件的result属性包含了转换完成的数据
            base64String = event.target.result;
            // 输出Base64编码的字符串
            resolve(base64String)
        };
        // 使用readAsDataURL方法开始转换Blob为Base64
        reader.readAsDataURL(blob);
    })
}


/**
* base64转图片File
* @param {String} base64 图片base64
* @param {String} fileName 图片名称| 默认 → imgName
* @returns File 返回转换后的file数据类型
*/
export function base64ToFile (base64, fileName = 'imgName') {
    // 将base64按照 , 进行分割 将前缀  与后续内容分隔开
    let data = base64.split(','),
        // 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等)
        type = data[0].match(/:(.*?);/)[1],
        // 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp)
        suffix = type.split('/')[1],
        // 使用atob()对base64数据进行解码  结果是一个文件数据流 以字符串的格式输出
        bstr = window.atob(data[1]),
        // 获取解码结果字符串的长度
        n = bstr.length,
        // 根据解码结果字符串的长度创建一个等长的整形数字数组
        // 但在创建时 所有元素初始值都为 0
        u8arr = new Uint8Array(n)

    // 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元
    while (n--) {
        // charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元
        u8arr[n] = bstr.charCodeAt(n)
    }
    // 利用构造函数创建File文件对象
    // new File(bits, name, options)
    const file = new File([u8arr], `${fileName}.${suffix}`, {
        type: type
    })
    // 返回file
    return file
}

// base64 转 blob
export function dataURItoBlob(base64Data) {
    var byteString;

    if(base64Data.split(',')[0].indexOf('base64') >= 0)
        byteString = atob(base64Data.split(',')[1]);//base64 解码
    else{
        byteString = unescape(base64Data.split(',')[1]);
    }
    var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0];//mime类型

    // var arrayBuffer = new ArrayBuffer(byteString.length); //创建缓冲数组
    // var ia = new Uint8Array(arrayBuffer);//创建视图
    var ia = new Uint8Array(byteString.length);//创建视图
    for(var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }
    var blob = new Blob([ia], {
        type: mimeString
    });
    return blob;
}
/**
* 压缩图片  返回base64
* @param {base64} imgFile 图片base64
* @param {Number} maxSize 上传压缩图片的大学| 默认 → 50 * 1024 kb
* @returns File 返回转换后的file数据类型
*/
export function compressImg(imgFile, maxSize = 50 * 1024) {
    return new Promise((resolve, reject) => {
        var img = new Image();
        img.src = imgFile
        console.log('imgFile', imgFile)
        
        img.onload = function () {
            var canvas = document.createElement('canvas');
            var ctx = canvas.getContext('2d');
            var width = img.width;
            var height = img.height;
            canvas.width = width;
            canvas.height = height;
            ctx.drawImage(img, 0, 0, width, height);
            var quality = 0.8;
            let newBase64Image = canvas.toDataURL('image/jpeg', quality);

            let fileSize = getBase64ImageSize(newBase64Image);
            if (fileSize > maxSize) {
                const qualityArr = [], step = 0.01;
                for (let i = step; i <= quality; i += step) {
                    // qualityArr.push(parseFloat(i.toFixed(2)));
                    qualityArr.push(parseFloat(i));
                }
                let left = 0,
                    right = qualityArr.length - 1;
                do {
                    console.log('循环次数fileSize', fileSize)
                    const mid = Math.floor((left + right) / 2);
                    newBase64Image = canvas.toDataURL('image/jpeg', qualityArr[mid]);
                    fileSize = getBase64ImageSize(newBase64Image);
                    if (fileSize > maxSize) {
                        right = mid - 1;
                    } else {
                        left = mid + 1;
                    }
                } while (left <= right);
            }
            // 对resultBlob做一些事情,比如从它创建一个新图像或保存它。
            console.log('压缩后的文件newBase64Image', newBase64Image)
            console.log('压缩后的文件fileSize', fileSize)
            resolve(newBase64Image)
        }
    })

}
// 计算base64编码图片大小
function getBase64ImageSize(base64) {
    const indexBase64 = base64.indexOf('base64,');
    if (indexBase64 < 0) return -1;
    const str = base64.substr(indexBase64 + 6);
    // 大小单位:字节
    return (str.length * 0.75).toFixed(2);
}

参考

GitHub 加速计划 / eleme / element
54.06 K
14.63 K
下载
A Vue.js 2.0 UI Toolkit for Web
最近提交(Master分支:3 个月前 )
c345bb45 7 个月前
a07f3a59 * Update transition.md * Update table.md * Update transition.md * Update table.md * Update transition.md * Update table.md * Update table.md * Update transition.md * Update popover.md 7 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐