资讯专栏INFORMATION COLUMN

JS压缩上传图片

luxixing / 3013人阅读

摘要:读取文件文件对象加载图片图片地址的图片转图片转图片对象图片质量到之间缩放比例到之间超过这个值无法生成,在上方式一低版本兼容性差些文件类型文件大小质量大小方式二文件类型文件大小质量大小上传上传的地址文件对象处理上传进度上传中反馈

 * @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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80936.html

相关文章

  • 前端文件上传(js/vue.js/axios/canvas图片压缩)

    摘要:哈哈主要还是我嫌麻烦四上传图片这里的页面样式,图片压缩和预览都和上面一样,这里我主要配置一下的,让接口能够成功上传。如果想让用户有更好的体验,可以对图片进行一下压缩和本地预览。 一、通过Form表单提交上传 HTML enctype属性必不可少 上面一种方法通过表单自有属性进行提交,看似简单,但是也有其最大的缺点,那就是提交...

    Luosunce 评论0 收藏0
  • 前端文件上传(js/vue.js/axios/canvas图片压缩)

    摘要:哈哈主要还是我嫌麻烦四上传图片这里的页面样式,图片压缩和预览都和上面一样,这里我主要配置一下的,让接口能够成功上传。如果想让用户有更好的体验,可以对图片进行一下压缩和本地预览。 一、通过Form表单提交上传 HTML enctype属性必不可少 上面一种方法通过表单自有属性进行提交,看似简单,但是也有其最大的缺点,那就是提交...

    Lsnsh 评论0 收藏0
  • JS图片压缩上传(单张)

    摘要:环境,这里的指到实例一图片压缩文件类型是图片格式,文件压缩后对象,,容器或者回调函数开始读取指定对象中的内容读取操作完成时返回一个格式的字符串开始压缩利用数据化图片进行压缩图片转指到默认按比例压缩默认图片质量为生成创建属性节点图像质量值越 *vue+webpack环境,这里的that指到vue实例 一、图片压缩 /* file:文件(类型是图片格式), ...

    KaltZK 评论0 收藏0
  • 结合Vue.js的前端压缩图片方案

    摘要:图片文件大小减小后,上传速度自然会提升,在同样的并发下,后台处理的速度也会得到提升,用户体验得到提升。 这是一个很简单的方案。嗯,是真的。 为什么要这么做? 在移动Web蓬勃发展的今天,有太多太多的应用需要让用户在移动Web上传图片文件了,正因如此,我们有些困难必须去攻克: 低网速下上传进度缓慢,用户体验差 高并发下,后台处理较大的上传文件压力大 或许有更多... 在攻克上面的一些...

    sutaking 评论0 收藏0
  • 移动端图片上传旋转、压缩的解决方案

    摘要:上传的文件经过就可以实现预览图片了,这方面不清楚的可以查看进阶系列文件上传下载旋转旋转需要用到的方法。 前言 在手机上通过网页 input 标签拍照上传图片,有一些手机会出现图片旋转了90度d的问题,包括 iPhone 和个别三星手机。这些手机竖着拍的时候才会出现这种问题,横拍出来的照片就正常显示。因此,可以通过获取手机拍照角度来对照片进行旋转,从而解决这个问题。 Orientatio...

    blair 评论0 收藏0

发表评论

0条评论

luxixing

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<