前端图片gizp压缩

118 阅读1分钟

图片gzip压缩

gzip.js
/**
 * 使用canvas压缩图片
 */
/**
 * 将base64数据装换成file对象
 * @param dataurl base64数据
 * @param filename file对象文件名
 * @returns {File}
 */
export function base64ToFile(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});
}

/**
 *
 * @param files 上传file对象
 * @param transSize 压缩后文件的大小
 * @param ext 压缩后文件扩展名
 * @returns {Promise<any>}
 */
export function gzipPic(files, transSize, ext) {
    // 将file对象转换成blob对象供img标签使用
    var url = window.URL.createObjectURL(files)
    var file = files
    var img = new Image()
    img.src = url
    // 返回Promise对异步生成的新的file对象进行处理
    return new Promise((resolve, reject) => {
        img.onload =function(){
            var w = this.width
            var h = this.height
            var max = w >= h ? w : h
            var finalW,finalH
            if (max <= transSize) {
                finalW = w
                finalH = h
            } else {
                var rate = w/h
                var scale = transSize / max
                if (w >= h) {
                    finalW = w * scale
                    finalH = finalW / rate
                }  else {
                    finalH = h * scale
                    finalW = finalH * rate
                }
            }
            var canvas = document.createElement('canvas')
            canvas.width = finalW
            canvas.height = finalH

            var cxt = canvas.getContext('2d')
            //cxt.rect(0,0,finalW,finalH)
            cxt.drawImage(img,0,0,finalW,finalH)
            var base64 = canvas.toDataURL(ext || 'image/jpeg', 1)
            var newFile = base64ToFile(base64, file.name)
            resolve(newFile)
        }
    })
}

使用:

//html结构
<input @change="phone($event)" type="file" capture="camera" />

phone(e) {
    let fs = e.target.files[0];
    //源文件大于3M压缩
	if (e.target.files[0].size > 3 * 1024 * 1024) {
		fs = await gzipPic(e.target.files[0], 256);
		if (fs.size > 3 * 1024 * 1024) {
            //压缩后还大于3M的逻辑
		}
    }else{
        //源文件小于3M正常处理
    }
}

使用input上传源文件

upload.js
import { gzipPic } from './gzip'
export function uploadFile({ file, onUploadProgress, url }) {
    url = url || '/snsV2/uploadPic.php'
    let xhr = null
    if (window.XMLHttpRequest) {
        // webkit
        xhr = new XMLHttpRequest()
    } else {
        // IE
        xhr = new ActiveXObject('Microsoft.XMLHTTP')
    }
    xhr.open('POST', url , true)
    return new Promise((resolve, reject) => {
        xhr.onreadystatechange = function () {
            //后端接受完毕
            if(xhr.readyState == 4){
                resolve(xhr.responseText)
            }
        }
        xhr.send(file)
    })
}

/**
 * 文件上传处理
 * @param files 文件对象
 * @param isZip 是否压缩 boolean
 * @param success 上传成功后处理函数
 * @param transSize 压缩后文件的大小
 * @param ext 压缩后文件的后缀
 * @param onUploadProgress 文件上传进度处理
 * @param url 上传的url
 * @param fileName 控件名称
 * @returns {Promise<void>}
 * 方法默认接口只传一个参数(参数名默认是file)
 */
export async function handleFile({ files, isZip, success, transSize, ext, onUploadProgress, url, fileName}) {
    let file = fileName || 'file'
    for (let i = 0;i < files.length; ++i){
        let formData = new FormData()
        if (isZip) {
            let res = await gzipPic(files[i], transSize, ext)
            formData.append(file, res)
        } else {
            formData.append(file, files[i])
        }
        uploadFile({
            file: formData,
            onUploadProgress,
            url
        }).then((res) => {
            success && success(res)
        })
        formData.delete(file)
    }
}

使用:

<input @change="handleAddImg($event)" type="file" capture="camera" />

方法一:用handleFile方法上传图片(只能上传一个参数)

// 上传图片(用)
handleAddImg(e) {
	if (e.target.value) {
		let files = e.target.files;
		handleFile({
			files,
                        isZip: true,
			transSize: 1500,
			success: function(response) {
			let res = JSON.parse(response);
			if (res.code === 20000) {
				// 上传成功逻辑:图片地址res.data.url
			} else {
				//上传失败逻辑
				}
			}
		});
	}
},

方法二:用uploadFile方法上传图片(可上传多个参数)

handleAddImg(e){
	if(e.targe.value){
		let fs = e.target.files[0];
        let formData = new FormData();
		formData.append('file', fs);
		formData.append('token', 'xxxx');
		formData.append('type', 'ooo');
                uploadFile({ file: formData, url: '/v2/realname/abroad/uploadImg.php' })
			.then((info) => {
				let res = JSON.parse(info);
				if (res.code == 20000) {
                                    res = res.data;
                                    //上传成功逻辑
				} else {
                                    //上传失败逻辑
				}
			})
             .catch((err) => {});
    }
}