js压缩图片

351 阅读2分钟

在做移动端图片上传的时候,用户传的都是手机本地图片,而本地图片一般都相对比较大,拿iphone6来说,平时拍很多图片都是一两M的,如果直接这样上传,那图片就太大了,如果用户用的是移动流量,完全把图片上传显然不是一个好办法。

在移动端压缩图片并且上传主要用到filereader、canvas 以及 formdata 这三个h5的api。逻辑并不难。整个过程就是:
(1)用户使用input file上传图片的时候,用filereader读取用户上传的图片数据(base64格式)
(2)把图片数据传入img对象,然后将img绘制到canvas上,再调用canvas.toDataURL对图片进行压缩
(3)获取到压缩后的base64格式图片数据,转成二进制塞入formdata,再通过XmlHttpRequest提交formdata。

<input 
      v-show="!imgSrc && !imgload"
      type="file" 
      accept="image/png,image/gif,image/jpeg" 
      class="upload-input" 
      @change="uploadFunc"
/>
compressImage(file) {
    // 参数file,是通过input 选择本地文件获取的
    return new Promise((resolve) => {
        const { type, name } = file;
        let img = new Image();
        let reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = function(e) {
            // 文件加载成功后去转成Img对象,为了拿到图片的原始宽高
            img.src = e.target.result;
            img.onload = function() {
                // 创建画布canvas
                let canvas = document.createElement('canvas');
                let content = canvas.getContext('2d');
                // 设置画布的宽高
                canvas.width = img.width;  // 需要压缩到的图片宽度
                canvas.height = img.width * (img.height / img.width);
                // 将图片画在画布上
                content.drawImage(img, 0, 0, canvas.width, canvas.height);
                //画布转成blob格式的图片
                canvas.toBlob(function(blob) {
                    // blob 格式的图片 转成file对象,这里主要看接口支不支持blob格式的文件上传,如果支持就没有必要转
                    let file = new File([blob], name, { type: type });
                    resolve({type: type, compressFile: file})
                }, `image/${type.split('/')[1]}`, 0.7);  // 0.7 是文件压缩程度
            }
        }
    });
},
uploadFunc(e) {
    let file = e.target.files[0];
    if (file.size) {
        const isLt2M = file.size / 1000 / 1000 < 15;
        if (!isLt2M) {
            Toast('上传图片大小不能超过 15MB!');
            return;
        }
    }
    let minImage = this.compressImage(file);
    minImage.then(result => {
        console.log('imgtype----' + result.type);
        this.file = result.compressFile;
        this.imgload = true;
        let param = new FormData();
        param.append('file', result.compressFile);
        let config = {
            headers: {'Content-Type': 'application/x-www-form-urlencoded'}
        };
        axios.post('/duihuan/order/ajax_upload_img', param, config).then(res => {
            if(res.data.error_code === 0) {
                this.imgSrc = res.data.data.url;
            } else {
                Toast(res.data.error_msg);
            }
            this.imgload = false;
        });
    });

},

使用压缩后,上传一个5.4兆的图片,发现压缩后的上传的图片大小是1.1兆(1066753/1024/1024),接口请求时间也由原先的六七秒降为两秒多

WechatIMG167.png