以移动端为例,在H5上传图片时,由于机型 / 网速 / 流量等限制,在低版本机型上经常会出现上传的图片太大导致上传很慢甚至崩溃的情况,所以需要对在某些情况下需要对上传的图片进行压缩上传。

以下以移动端使用Vue框架为例:

(以下主要实现思路来自张鑫旭大神的博客:?https://www.zhangxinxu.com/wordpress/2017/07/html5-canvas-image-compress-upload/)

话不多说进入正题

第一步:使用原生input上传图片

<input type="file" class="file-btn" @change="changeImg($event)" />

上面这句代码中可以发现,我没有指定上传的文件的格式,因为在之前的开发过程中发现,input在设置了accpet=“image/*”之后,在某些低版本安卓机(微信浏览器)上,会出现上传jpeg格式的图片无法触发input的change的事件的情况,所以后来就把input的图片类型去掉了,验证文件类型在change事件触发后处理或者交由后端校验。

第二步:将图片利用canvas的drawImage进行按比例重绘

在接收到需要上传的图片之后,我们可以做一些限制操作,比如限制上传图片的大小 / 校验文件的格式等等,这里就不写出来了。直接切入正题:

changeImg(e){const imgFile = e.target.files[0];const zipImgPromise = (imgFile) => {return new Promise((resolve, reject) => {let reader = new FileReader();    // 定义一个fileReaderreader.readAsDataURL(imgFile);    // 将图片转换成base64后可以得到图片的宽高let img = new Image();reader.onload = () => {img.src = reader.result;}img.onload = () => {// 图片原始尺寸let originWidth = img.width;let originHeight = img.height;let canvas = document.createElement('canvas');let context = canvas.getContext('2d');// 最大尺寸限制let maxWidth = 800, maxHeight = 800;// 目标尺寸let targetWidth = originWidth, targetHeight = originHeight;// 图片尺寸超过400x400的限制if (originWidth > maxWidth || originHeight > maxHeight) {if (originWidth / originHeight > maxWidth / maxHeight) {// 更宽,按照宽度限定尺寸targetWidth = maxWidth;targetHeight = Math.round(maxWidth * (originHeight / originWidth));} else {targetHeight = maxHeight;targetWidth = Math.round(maxHeight * (originWidth / originHeight));}}// canvas对图片进行缩放canvas.width = targetWidth;canvas.height = targetHeight;// 清除画布context.clearRect(0, 0, targetWidth, targetHeight);// 图片压缩context.drawImage(img, 0, 0, targetWidth, targetHeight);// canvas转换成dataUrllet dataUrl = canvas.toDataURL('image/png');// 转换成formdata格式用于上传图片let blob = this.dataURItoBlob(dataUrl);if (blob) {resolve(blob);} else {reject(new Error('Error!!'));}}});};zipImgPromise(imgFile).then(blob => {let file = new FormData(); // 创建form对象file.append('file', blob, imgFile.name); // 通过append向form对象添加数据file.append('chunk', '0'); // 添加form表单中其他数据let config = {headers: {'Content-Type': 'multipart/form-data'}};// 开始上传图片// ...// 这里用于执行上传图片的XHR操作// ...$http.post(‘api’, file, config).then(res => {// ...}).catch(error => {// ...});}).catch(error => {// 处理zipImgPromise和前一个回调函数运行时发生的错误console.log('发生错误', error);});Ï
},
dataURItoBlob(dataURI) {let byteString = atob(dataURI.split(',')[1]);let mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]let ab = new ArrayBuffer(byteString.length);let ia = new Uint8Array(ab);for (let i = 0; i < byteString.length; i++) {ia[i] = byteString.charCodeAt(i);}let bb = new Blob([ab], { "type": mimeString });return bb;
}

主要思路

其上传主要思路其实就是按比例缩放图片,主要运用了canvasdrawImage()方法。

canvasdrawImage()方法API如下:

context.drawImage(img, dx, dy);
context.drawImage(img, dx, dy, dWidth, dHeight);
context.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);

dx, dy, dWidth, dHeight——表示在canvas画布上规划处一片区域用来放置图片,dx, dy为canvas元素的左上角坐标,dWidth, dHeight指canvas元素上用在显示图片的区域大小。如果没有指定sx,sy,sWidth,sHeight这4个参数,则图片会被拉伸或缩放在这片区域内。

所以我们这里简单来说是通过的将一张原始尺寸是2000*1300的图片,通过刚刚说的canvas的drawImage()方法,把尺寸限制为400*300大小,很简单,主要代码就是下面这4句

let canvas = document.createElement('canvas');
let context = canvas.getContext('2d');
canvas.width = 400;
canvas.height = 300;
// 核心JS
context.drawImage(img,0,0,400,300);

这里通俗来说就是把一张大的图片,直接画在一张小的画布上,这样大图片就变成了小图片,压缩图片就是这样实现的。(听起来有点amazing~)

所以经过了图片→canvas压缩→图片的这三个步骤,我们的压缩图片就完成啦~~

前端实现图片压缩上传功能相关推荐

  1. 基于vue + axios + lrz.js 微信端图片压缩上传

    业务场景 微信端项目是基于Vux + Axios构建的,关于图片上传的业务场景有以下几点需求: 1.单张图片上传(如个人头像,实名认证等业务) 2.多张图片上传(如某类工单记录) 3.上传图片时期望能 ...

  2. web 前端图片优化之--图片压缩上传

    移动前端-图片压缩上传实践  此前有同事跟我聊过关于移动端用canvas压缩图片后再上传的功能,最近有了点空闲时间,所以就实践了一下.demo效果链接在文章底部贴出. 在做移动端图片上传的时候,用户传 ...

  3. JS前端图片压缩上传

    JS前端图片压缩上传重点知识 最近在做一个手机端的图片上传,写了一个比较符合自己要求的方法,可供参考 在做这个功能模块时,我遇到了以下问题,都花费了大量时间: 1. 不知道怎么压缩图片,(代码和方法) ...

  4. 前端图片压缩上传(压缩篇)

    为什么说这是一篇比较适合小白的前端图片压缩文章呢?因为我也是一个刚工作半年的前端小白,最近接到了一个前端图片压缩上传的任务,通过各种百度博客完成了这项任务,但是任务完成后对各种技术细节却还不是特别理解 ...

  5. vue本地上传并预览php,vue.js 实现图片本地预览 裁剪 压缩 上传功能

    以下代码涉及 Vue 2.0 及 ES6 语法. 目标 纯 javascrpit 实现,兼容ie9及以上浏览器,在本地做好文件格式.长宽.大小的检测,减少浏览器交互. 现实是残酷的,为了兼容Ie9 还 ...

  6. 前端图片压缩上传(纯js的质量压缩,非长宽压缩)

    前端图片压缩上传(纯js的质量压缩,非长宽压缩) 此demo为大于1M对图片进行压缩上传 若小于1M则原图上传,可以根据自己实际需求更改. demo源码如下: <!DOCTYPE html> ...

  7. 基于Plupload的图片压缩上传

    前言 这里的上传工具基于JQuery.Plupload 传送门:Plupload官方.中文文档 为什么要做图片压缩? 现在手机拍照都快10M了,但是有时候图片上传只要看得清楚就可以了,比如上传身份证2 ...

  8. 移动端实现图片压缩上传

    移动端实现图片压缩上传 目前来说,HTML5的各种新API都在移动端的webkit上得到了较好的实现.根据查看caniuse,本demo里使用到的FileReader.Blob.Formdata对象均 ...

  9. [html] 如何使用html5进行图片压缩上传?

    [html] 如何使用html5进行图片压缩上传? 1.获取到图片的base64格式: 2.图片加载完成后,把图片转化为canvas: 3.使用canvas的toDataURL按照自己的需要进行压缩: ...

最新文章

  1. jQuery的选择器(一)
  2. python服务器消息分发_Python实现分发数据块到多台服务器上
  3. php提示行号,在php中使用trigger_错误时如何获得正确的行号?
  4. api 定位 微信小程序 精度_聊聊微信小程序内置地图定位的精确性
  5. 媒体应用大数据,先解决三大难题
  6. net core 3.0 之Grpc新特性小试牛刀
  7. java官方 jax rs_jboss7 Java API for RESTful Web Services (JAX-RS) 官方文档
  8. IDEA如何删除无用war包
  9. 【算法】剑指 Offer 56 - II. 数组中数字出现的次数 II 【重刷】
  10. Hadoop(二)搭建Hadoop集群
  11. java filter bme_节点红色,想截断BME280传感器的结果
  12. Exchange 2010 使用http访问 OWA
  13. xp系统安装金蝶k3服务器配置,XP单机版安装金蝶K3的13.1版本号,金蝶K3Wise安装步骤,安装成功...
  14. 微生物qPCR定量检测
  15. c语言 小学生测试题,C语言编程测试题(含答案)
  16. sql server 取当天所在第几周
  17. 绑定美版office365密钥_美版Microsoft/微软Office 365个人版怎么激活?
  18. 更加简便的使用VSS
  19. **Hadoop Ubuntu系统搭建攻略全详细!!!附带Hadoop搭建成功后测试案例**
  20. AXI总线详解-AXI4读写操作时序及AXI4猝发地址及选择

热门文章

  1. 说小台芒本可儿傲娇又冷艳,也不看看颜值和身段?
  2. 可禁用计算机服务,Windows 10系统下哪些服务可以关闭?
  3. QUECTEL上海移远4G通讯CAT4模组EC20CEFAG模块串口调试指南之02【EC20模组硬件供电和开关机复位操作】
  4. Codeforces 869C The Intriguing Obsession 组合数取模
  5. 计算机专业可取证书名称,职业中专计算机维修专业发的职业资格证书名称叫什..._出版资格_帮考网...
  6. H5监听摇一摇和手机倾斜事件(重力感应)
  7. android Wifi连接及检测信号强度
  8. 会员制实现C2B定制有机农产品,被中粮我买投资的良食网这样卖有机生鲜
  9. 从零开始—仿牛客网讨论社区项目(一)
  10. 当且仅当函数依赖a→b在r上成立_数据库第06章关系数据理习题课.ppt