使用element-ui实现多图上传、前端压缩功能

1,853 阅读2分钟

这是我的千日蜕变计划第三篇,我计划在未来的1000天,三天更新一篇博客。希望大家监督,也希望自己可以坚持。

功能分析

  • 利用element-ui的图片上传组件实现多图上传
  • 前端实现图片压缩(等比例压缩或者质量压缩不缩放百分比)

html部分代码

// 这里我把element-ui的上传组件隐藏,用了一个单独的按钮调用上传的方法
<el-upload
    multiple
    style="display: none;"
    :action="updateImgUrl"
    :before-upload="beforeAvatarUpload"
    :on-success="handleAvatarSuccess"
    :on-error="handleAvatarError">
    <button ref="trueUpdateFile" size="small" type="primary">点击上传</button>
</el-upload>
<button ref="trueUpdateFile" size="small" type="primary">点击上传</button>

JS代码部分

export default {
    data() {
        return {
            imgQuality: 0.5 //压缩图片的质量
        }
    }
    methods: {
        // 上传文件
        handleUpdateFile() {
            this.$refs['trueUpdateFile'].click()
        },
        // 上传之前
        beforeAvatarUpload(file) {
            const isJPGORPNG = file.type === 'image/jpeg' || file.type === 'image/png';
            const isLt10M = file.size / 1024 / 1024 < 10;
            const imgSize = file.size / 1024 / 1024;
            // 这里根据不同的图片质量,使用不同的压缩比例
            if (imgSize > 2) {
                this.imgQuality = 0.3;
            } else if(imgSize > 1) {
                this.imgQuality = 0.5;
            } else if(imgSize > 0.2) {
                this.imgQuality = 0.8;
            } else {
                this.imgQuality = 1;
            }
            this.tempimgNum++;
            if (!isJPGORPNG) {
                this.uploadTips = '上传';
                this.updateLoading = false;
                common.showMessage(Message, '上传头像图片只能是 JPG         格式或者png格式!', 'error', '1000', function () {});
                }
            if (!isLt10M) {
                this.uploadTips = '上传';
                this.updateLoading = false;
                common.showMessage(Message, '上传头像图片大小不能超过 10MB!', 'error', '1000', function () {});
            }
            const _this = this
            if(imgSize > 1) {
                return new Promise(resolve => {
                const reader = new FileReader()
                const image = new Image()
                image.onload = (imageEvent) => {
                    const canvas = document.createElement('canvas');
                    const context = canvas.getContext('2d');
                    const width = image.width; // 如果需要等比例压缩,这里*质量。image.width * this.imgQuality.高度也这样操作
                    const height = image.height;
                    canvas.width = width;
                    canvas.height = height;
                    context.clearRect(0, 0, width, height);
                    context.drawImage(image, 0, 0, width, height);
                    const dataUrl = canvas.toDataURL(file.type, this.imgQuality);
                    //如果需要等比例压缩,这里
                    //const dataUrl = canvas.toDataURL(file.type);
                    const blobData = _this.dataURItoBlob(dataUrl, file.type);
                    resolve(blobData)
                }
                reader.onload = (e => { image.src = e.target.result; });
                    reader.readAsDataURL(file);
                })
            }
            return isJPGORPNG && isLt10M;
        },
        dataURItoBlob(dataURI, type) {
            var binary = atob(dataURI.split(',')[1]);
            var array = [];
            for(var i = 0; i < binary.length; i++) {
                array.push(binary.charCodeAt(i));
            }
            return new Blob([new Uint8Array(array)], {type: type});
        },
        handleAvatarSuccess(res) {
            if(res) {
                this.attachIds.push(res)
            }
            // 这里判断多图是否上传完成
            if(this.tempimgNum === this.attachIds.length) {
                this.uploadTips = '';
                this.getReceptionId()
            }
        },
        handleAvatarError() {
            this.updateLoading = false;
        },
        getReceptionId() {
            let formData = common.getFormFormatData({patientId: this.childData.patientId});
            axios({
                method: 'post',
                url: this.getPatientLastId,
                data: formData,
                config: common.getFormHeaders()
            }).then((res) => {
                this.handleSavePatientAttach(res.data)
            }).catch((e) => {
                common.showMessage(Message, e.response.data.message, 'error', '1000', function () {});
            }).finally(() => {
                this.updateLoading = false;
                this.uploadTips = '上传';
            });
        },
        // 最后确认保存
        handleSavePatientAttach(reception_id) {
            let attach_ids = this.attachIds.join(',');
            let formData = common.getFormFormatData({
                patientId: this.childData.patientId,
                attachIds: attach_ids,
                receptionId: reception_id,
                description: ''
            });
            axios({
                method: 'post',
                url: this.savePatientAttachUrl,
                data: formData,
                config: common.getFormHeaders()
            }).then((res) => {
                common.showMessage(Message, '图片上传成功', 'success', '1000', () => {
                this.radioClick()
            });
            }).catch((e) => {
                common.showMessage(Message, e.response.data.message, 'error', '1000', () => {
            });
            }).finally(() => {
                // 上传结束后,初始化临时数据
                this.tempimgNum = 0;
                this.attachIds = [];
                this.loading = false;
                this.updateLoading = false;
                this.uploadTips = '上传';
            });
        },
    }
}

以上代码有很多涉及到业务代码。主要用来留存前端压缩图片的方法。

我是海明月,前端小学生。