JS压缩上传图片

数字踏浪使
• 阅读 2103
 * @Date: 2016/11/17  0017
 * @Time: 10:14
 * @Author: lxbin
 *
 * Created with JetBrains WebStorm.
 */

/**
 * http://leonshi.com/2015/10/31/html5-canvas-image-compress-crop/
 * http://jafeney.com/2016/08/11/20160811-image-upload/
 * http://ilovetile.com/3506
 */

/**
 * 读取文件
 * @param file 文件对象
 * @return {Promise}
 */
function readFileAsync(file) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.onload = e => resolve(readFile.target.result)
        reader.onerror = e => reject(new Error('Could not read file'))
        reader.readAsDataURL(file)
    })
}

/**
 * 加载图片
 * @param url 图片地址
 * @return {Promise}
 */
function loadImageAsync(url) {
    return new Promise((resolve, reject) => {
        const image = new Image()
        image.onload = () => resolve(image)
        image.onerror = () => reject(new Error('Could not load image at ' + url))
        image.src = url
    })
}

/**
 * base64的图片dataUri转Blob
 * @param dataURI
 * @return {*}
 */
function dataURItoBlob(dataURI) {
    // convert base64 to raw binary data held in a string
    // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
    const byteString = atob(dataURI.split(',')[1]);

    // separate out the mime component
    const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]

    // write the bytes of the string to an ArrayBuffer
    const ab = new ArrayBuffer(byteString.length);
    const ia = new Uint8Array(ab);
    for (let i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }

    // write the ArrayBuffer to a blob, and you're done
    return new Blob([ab], {type: mimeString});

    // Old code
    // const bb = new BlobBuilder();
    // bb.append(ab);
    // return bb.getBlob(mimeString);
}

/**
 * 图片转Blob
 * @param image 图片对象
 * @param quality 图片质量(0到1之间)
 * @param scale 缩放比例(0到1之间)
 * @return {Promise}
 */
function imageToBlob(image, quality, scale) {
    return new Promise((resolve, reject) => {
        try {
            let canvas = document.createElement('canvas')
            canvas.width = image.naturalWidth * scale
            canvas.height = image.naturalHeight * scale
            while (canvas.width >= 3264 || canvas.height >= 2448) {//超过这个值base64无法生成,在IOS上
                canvas.width = canvas.naturalWidth * scale
                canvas.height = canvas.naturalHeight * scale
            }

            let ctx = canvas.getContext('2d').drawImage(image, 0, 0, canvas.width, canvas.height)

            //方式一:低版本兼容性差些
            //canvas.toBlob(function (blob) {
            //    console.group('[Leo]file compress to blob')
            //    console.log('文件类型 => ' + image.type)
            //    console.log('文件大小 => ' + (image.size / 1024 / 1024).toFixed(2) + 'M')
            //    console.log('blob质量 => ' + quality)
            //    console.log('blob大小 => ' + (blob.size / 1024 / 1024).toFixed(2) + 'M')
            //    console.groupEnd()
            //    resolve(blob)
            //}, 'image/jpeg', quality)

            //方式二:
            const base64 = canvas.toDataURL('image/jpeg', quality);
            const blob = dataURItoBlob(base64);
            blob.name = blob.filename = image.name
            console.group('[Leo]image compress to blob')
            console.log('文件类型 => ' + image.type)
            console.log('文件大小 => ' + (image.size / 1024 / 1024).toFixed(2) + 'M')
            console.log('blob质量 => ' + quality)
            console.log('blob大小 => ' + (blob.size / 1024 / 1024).toFixed(2) + 'M')
            console.groupEnd()
            resolve(blob);
        } catch (e) {
            reject(new Error("Image could not convert to blob :" + e))
        }
    })
}

/**
 * Ajax上传
 * @param uri 上传的Action地址
 * @param file 文件对象
 * @return {Promise}
 */
function uploadFile(uri, file) {
    return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest()
        if (xhr.upload) {
            xhr.upload.addEventListener("progress", (e) => {// 处理上传进度
                if (e.lengthComputable) {
                    let percent = (e.loaded / e.total * 100).toFixed(2) + '%'
                    console.log("上传中(" + percent + ")");
                    //TODO:反馈到DOM里显示
                } else {
                    console.log('unable to compute');
                }
            }, false)
        }
        xhr.onreadystatechange = (e) => {// 文件上传成功或是失败
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    resolve(xhr.responseText)// 上传成功
                } else {
                    reject(xhr.responseText)// 上传出错处理
                }
            }
        }
        xhr.open("POST", uri, true)// 开始上传
        let form = new FormData()
        form.append("filedata", file, file.name)
        xhr.send(form)
    })
}

/**
 * 上传文件
 * @param file 文件对象
 * @param quality 图片质量(0到1之间)
 * @param scale 缩放比例(0到1之间)
 */
export default async function fileUpload(file, quality, scale) {
    try {
        let fileUrl = await readFileAsync(file)
        let image = await loadImageAsync(fileUrl)
        image.name = file.name
        let blob = await imageToBlob(image, quality, scale)
        let upload = await uploadFile(blob)
        return upload
    } catch (e) {
        console.log('file upload failed')
    }
}

http://leonshi.com/2015/10/31...
http://jafeney.com/2016/08/11...
http://ilovetile.com/3506

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Easter79 Easter79
3年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
双十一预售活动分析
2022年双十一促销活动已经开始,大家应该都提前开始关注今年双十一活动的时间表了吧?2022年10月24日晚8:00天猫双11预售时间,第一波销售时间10月31日晚8:0,第二波销售时间11月10日晚8:00;天猫双11的优惠力度是跨店每满30050
国庆假期玩不停双重好礼放肆领
自2021年10月1日00:00起至2021年10月7日24:00,新注册并激活(需全部完成账号注册的五个步骤,否则账号状态并未激活)AWS海外区域账户,填写页面下方表单,即可申领价值$200美元的AWS海外区域账户服务抵扣券直充到您的账户,用以抵扣服务消费,助您轻松体验多个云迁移应用场景。同时,您还可获赠AWS精美祥云纪念T恤一件。,仅限7天AW
AWS国庆双重礼,仅限7天
自2021年10月1日00:00起至2021年10月7日24:00,新注册并激活(需全部完成账号注册的五个步骤,否则账号状态并未激活)AWS海外区域账户,填写页面下方表单,即可申领价值$200美元的AWS海外区域账户服务抵扣券直充到您的账户,用以抵扣服务消费,助您轻松体验多个云迁移应用场景。同时,您还可获赠AWS精美祥云纪念T恤一件。,仅限7天$20
AWS国庆双重礼,仅限7天
自2021年10月1日00:00起至2021年10月7日24:00,新注册并激活(需全部完成账号注册的五个步骤,否则账号状态并未激活)AWS海外区域账户,填写页面下方表单,即可申领价值$200美元的AWS海外区域账户服务抵扣券直充到您的账户,用以抵扣服务消费,助您轻松体验多个云迁移应用场景。同时,您还可获赠AWS精美祥云纪念T恤一件。,仅限7天$20
Wesley13 Wesley13
3年前
Ubuntu与Win10周年版Ubuntu Bash性能对比
!Ubuntu与Win10周年版UbuntuBash性能对比Ubuntu与Win10周年版UbuntuBash性能对比(http://www.linuxprobe.com/wpcontent/uploads/2016/11/143929q6ttej7enjjzs1rw1.jpg)Windows的Linux子系统测试完成了所有测试,并随着
Wesley13 Wesley13
3年前
JS的部分部分疑问和小结
2015/9/1 1.在字符串中没有可以所需要查找的“X”的时候,返回的值 java:lastIndexof1 js:IndexOfundefined...2015/9/10 1.js:string.substr(start\,length\) 如,selecter.dmselectIndex.sub
Wesley13 Wesley13
3年前
ES6 新增的数组的方法
给定一个数组letlist\//wu:武力zhi:智力{id:1,name:'张飞',wu:97,zhi:10},{id:2,name:'诸葛亮',wu:55,zhi:99},{id:3,name:'赵云',wu:97,zhi:66},{id:4,na
数字踏浪使
数字踏浪使
Lv1
各有归舟,各有渡口。
文章
4
粉丝
0
获赞
0