前端js实现canvas压缩图片并上传

news2024/11/18 20:01:26

一. 上传前压缩图片的好处

  1. 可以减少用户的等待时间,提升使用体验,目前手机拍摄的图片文件大小一般在几 M 左右,文件直接上传时会有卡顿现象。
  2. 可以减少服务端存储空间
  3. 再次回去图片资源是也可以快速的加载。虽然目前阿里云的 oss 有相对应的 api 可以通过降低图片质量等方法减少体积,不过使用 canvas 可以直接减少源文件的体积。

因此我们很有必要对上传的图片进行压缩。

二. 处理流程

主要包括以下流程:

  1. 用户通过van-uploader选择图片。
  2. 使用FileReader进行图片预览。
  3. 将图片绘制到canvas画布上,使用canvas画布的能力进行图片压缩todataurl()方式会把图片自动转成base64。
  4. 将压缩后的Base64(DataURL)格式的数据转换成Blob对象进行上传,或者直接上传base64格式,这个根据自己需求。
  5. 将图片上传服务端,上传时候创建Formdata对象实例 new FromData(),把base64或Blob,append()到Formdata里面请求服务端接口,提交图片。
  6. 上传成功,后台接口返回图片的URL。

三. 了解概念

在写代码之前,先来了解几个概念。当然也可以跳过这部分,直接看代码。

1)new FileReader()
我们先来看看官方文档的介绍 FileReader

FileReader 对象允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。

FileReader常用的两个方法如下:

FileReader.onload: 处理load事件。即该钩子在读取操作完成时触发,通过该钩子函数可以完成例如读取完图片后进行预览的操作,或读取完图片后对图片内容进行二次处理等操作。
FileReader.readAsDataURL():读取方法,并且读取完成后,result属性中将包含一个data: URL 格式的 Base64 字符串以表示所读取文件的内容(比如图片)。

在图片上传中,我们可以通过readAsDataURL()方法进行了文件的读取,并且通过result属性拿到了图片的Base64(DataURL)格式的数据,然后通过该数据实现了图片预览的功能。

2)new FormData()
我们先来看看官方文档的介绍 FormData 对象的使用

FormData 对象用以将数据编译成键值对,以便用XMLHttpRequest来发送数据。其主要用于发送表单数据,但亦可用于发送带键数据 (keyed data),而独立于表单使用。如果表单enctype属性设为 multipart/form-data,则会使用表单的submit()方法来发送数据,从而,发送数据具有同样形式。

let formdata = new FormData()
console.log(formdata)

打印

操作方法:new FormData()对象的作用以及使用方法

3)new Image()

我们先来看看官方文档的介绍 Image()

Image()函数将会创建一个新的HTMLImageElement实例。它的功能等价于 document.createElement('img')
Image对象是JS中的宿主(或内置)对象,他代表嵌入的图像。当我们创建一个Image对象时,就相当于给浏览器缓存了一张图片,Image对象也常用来做预加载图片(也就是将图片预先加载到浏览器中,当浏览图片的时候就能享受到极快的加载速度)。在HTML页面中,标签每出现一次,也就创建了一个Image对象。

建立图像对象:`let 图像对象名称=new Image([宽度],[高度])`
图像对象的属性: `border complete height hspace lowsrc name src vspace width`
图像对象的事件:`onabort onerror onkeydown onkeypress onkeyup onload`

在这里插入图片描述

var img = new Image(); //创建一个Image对象 ,会渲染为img标签
img.src = "17.png";  //相当于给浏览器缓存了一张图片
img.onload = function(){alert("img is loaded")};  //onload 事件在图片加载完成后立即执行。
img.onerror = function(){alert("error!")};  // 当图片加载出现错误,会触发,经常在该事件中将图片导向报错图片,以免页面上出现红色的叉叉
img.border="3px solid #ccc"; 

4)canvas的toDataURL()方法
我们先来看看官方文档的介绍HTMLCanvasElement.toDataURL()

HTMLCanvasElement.toDataURL() 方法返回一个包含图片展示的 data URI 。可以使用 type 参数其类型,默认为 PNG 格式。图片的分辨率为 96dpi。

语法:

canvas.toDataURL(type, encoderOptions);

参数:

type:图片格式,默认为 image/png,可以是其他image/jpeg等
encoderOptions:01之间的取值,主要用来选定图片的质量,只要导出为jpg和webp格式的时候此参数才有效果。默认值是0.92,超出范围也会选择默认值。

返回值:

返回值是一个数据url,是base64组成的图片的源数据、可以直接赋值给图片的src属性。

5)图片的展示方式有三种:分别为file(文件流)、blob(本地流)、base64(二进制流)

四. 代码实现

1)通过van-uploader来获取图片

<van-field name="business_license" :rules="[{ required: true, message: '请上传图片' }]">
     <template #input>
         <van-uploader
           :max-size="3000 * 1024"
           @oversize="onOversize"
           :after-read="afterReadLicense"
           :before-delete="deleteLicense"
           v-model="form.licenseArray"
           :max-count="1"
          />
     </template>
</van-field>
    //获取上传图片大小,进行压缩处理
  compressImg (file) {
      let quality = 1
      if (file.file.size / (1024 * 1024) > 1) {
        quality = 1 / Math.ceil(file.file.size / (1024 * 1024)) // 默认到1m以下
      }
      quality = quality / 2 // 默认质量减半(超过1m的图片,默认质量为500k)
      var that = this
      return new Promise(function (resolve, reject) {
        if (file == []) {
          reject(error)
        } else {
          if (that.isImageAutomaticRotation) {
            that.imgHandle(file.file, quality).then(res => {
              resolve(res)
            })
          } else {
            lrz(file.file, { quality: quality }).then(res => {
              resolve(res.base64)
            })
          }
        }
      })
    },
    // 这是图片上传压缩的核心所在,我们先使用CanvasRenderingContext2D.drawImage()方法将上传的图片文件在画布上绘制出来;
   // 再使用Canvas.toDataURL()将画布上的图片信息转换成base64(DataURL)格式的数据。
   imgHandle (file, quality) {
      return new Promise(function (resolve, reject) {
        let fileType = file.type
        let imgResult = ''
        let reader = new FileReader()
        reader.readAsDataURL(file)
        reader.onload = function () {
          let img = new Image() //先创建图片对象
          img.src = this.result
          let canvas = document.createElement('canvas')
          let ctx = canvas.getContext('2d')
          img.onload = function () { //图片加载完后
            // 做适配
            let width = 500
            if (img.width < 500) {
              width = img.width
            }
            canvas.width = width
            canvas.height = (img.height / img.width) * width
            ctx.drawImage(img, 0, 0, canvas.width, canvas.height)  //绘制图像;把大图片画在一张小画布上,压缩就这么实现了
            // 返回base64
            //quality表示导出的图片质量,只要导出为jpg和webp格式的时候此参数才有效果,默认值是0.92
            imgResult = canvas.toDataURL(fileType, quality)
            resolve(imgResult)
            
            // 这时可能后端要求我们传文件格式图片 base64转Blob
            // const blobImg = that.converrVase64UrlToBlob(imgResult , fileType)
            // resolve(blobImg)
          }
        }
        reader.onerror = function (error) {
          reject(error)
        }
      })
    },
  // base64转Blob
  converrVase64UrlToBlob (base64, mimeType) {
      // mimeType 图片类型,例如 mimeType='image/png'
      const bytes = window.atob(base64.split(',')[1]) // atob方法用于解码base64
      // 创建一个长度为 bytes.length 的 buffer(一个二进制文件), 它会分配一个 16 字节(byte)的连续内存空间,并用 0 进行预填充。
      const ab = new ArrayBuffer(bytes.length)

      // Uint8Array —— 将 ArrayBuffer 中的每个字节视为 0 到 255 之间的单个数字(每个字节是 8 位)。这称为 “8 位无符号整数”。
      const ia = new Uint8Array(ab)
      for (let i = 0; i < bytes.length; i++) {
        // 更改里面的初始化内容
        ia[i] = bytes.charCodeAt(i)
      }
      // 创建blob格式数据,并传入二进制文件和文件原本类型
      return new Blob([ia], { type: mimeType })
    },
    
  // 上传前置处理
  // 将图片上传到服务端
  afterReadLicense (file) {
      this.compressImg(file).then(res => {
        let formData = new FormData()
        formData.append('m_pic', res)  //append方法往formData里添加数据
        formData.append('token', sessionStorage.getItem('token'))
        console.log(formData.get('m_pic'), 'm_pic') //只能通过get方法查看添加的m_pic
        //请求接口,上传图片
        indexApi
          .uploadImg(formData)
          .then(response => {
            if (response.data.code === 200) {
              this.form.business_license = response.data.data.url //赋值
            } else {
              this.$toast.fail(response.data.message)
            }
          })
          .catch(error => {
            console.log(error)
          })
      })
    },
// 封装的上传图片接口
 uploadImg (val) {
    return formRequest({
      url: 'merchant/upload_img',
      method: 'post',
      data: val,
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    })
  },

注意:
在实际开发中,我们要不要把图片转化为FormData形式上传到服务端,这就看具体的业务需要了。
我们还可以把canvas压缩过的图片,通过axios请求 URL,并通过FormData附带额外的参数,上传到阿里云oss,会返回一个url,就是我们上传到阿里云的图片地址;然后前端拼成一个图片 url 用于from表单提交上传。

学习过程中参考了其他文章:
浅析图片上传及canvas压缩的流程(canvas图片压缩)
Canvas怎么实现上传并压缩图片
vue + elementUi + upLoadIamge组件 上传文件到阿里云oss

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/82399.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NPDP在国内有多少含金量?

产品经理国际资格认证&#xff0c;New Product Development Professional(NPDP)&#xff0c;由美国产品开发与管理协会&#xff08;PDMA&#xff09;所发起&#xff0c;是国际公认的唯一的新产品开发专业认证。是考察产品经理能力的证书。&#xff08;npdp产品经理资料文末&…

文本生成图像简述3--杂谈技术难点、研究意义、应用领域和目前的局限性

文本生成图像&#xff08;text-to-image&#xff09;指的是使用人工智能技术将文本转换为图像的过程&#xff0c;其可以根据给定文本生成符合描述的真实图像&#xff0c;其是多模态机器学习的任务之一&#xff0c;具有巨大的应用潜力&#xff0c;如视觉推理、图像编辑、视频游戏…

如何解决 Redis 数据倾斜、热点等问题

Redis 作为一门主流技术&#xff0c;应用场景非常多&#xff0c;很多大中小厂面试都列为重点考察内容 前几天有小伙伴学习时&#xff0c;遇到下面几个问题&#xff0c;来咨询 考虑到这些问题比较高频&#xff0c;工作中经常会遇到&#xff0c;这里写篇文章系统讲解下 问题描…

web网页设计期末课程大作业 HTML+CSS+JavaScript 美食餐饮文化主题网站设计 学生DW静态网页设计

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

关于vSphere HA Admission Control的讨论--2

上一期内容中预留的一些小问题首先做出回答&#xff1a; Q1&#xff1a;<若此时vCenter Server所在主机出现故障&#xff0c;vSphere HA是否能够正常完成故障响应&#xff1f;> A1&#xff1a;对于vSphere HA而言&#xff0c;在设计上采用主机通过FDM来管理HA的故障响应。…

天天刷 B 站,了解他们的评论系统是如何设计的吗?

今天给大家分享 B 站的评论系统的 组件化、平台化建设 通过持续演进架构设计&#xff0c;管理不断上升的系统复杂度&#xff0c;从而更好地满足各类用户的需求。 基础功能模块 评论的基础功能模块是相对稳定的。 1. 发布评论&#xff1a;支持无限盖楼回复。 2. 读取评论&…

DNS这个东西,你是真的了解了吗?

都说程序员是面向Google编程&#xff0c;殊不知当你输入 www.google.com 地址的时候&#xff0c;是否有想过&#xff0c;在回车的一瞬间浏览器如何将请求发送&#xff0c;如何到达目的地为你取得正确的数据。 遇到问题我们通常会打开浏览器&#xff0c;输入 www.google.com 回车…

EMQX+Prometheus+Grafana:MQTT 数据可视化监控实践

前言 作为一款全球下载量超千万的大规模分布式物联网 MQTT 服务器&#xff0c;最新发布的 EMQX 5.0 不仅全球首个达成单集群 1 亿 MQTT 连接支持&#xff0c;也是首个将 QUIC 引入 MQTT 的开创性产品。如今&#xff0c;EMQX 在各个行业为高可靠、高性能的物联网实时数据移动、…

阿里云服务器地域和可用区常见问题及官方资料解答

阿里云服务器同一地域分为多个可用区&#xff0c;不同地域的实例之间内网互不相通&#xff1b;选择靠近您客户的地域&#xff0c;可降低网络时延、提高您客户的访问速度。本文介绍阿里云地域和可用区的概念、选择指导、两者的关系以及阿里云支持的地域和可用区列表。 一.地域…

MySQL客户端的进阶操作

GreatSQL社区原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本&#xff0c;使用上与MySQL一致。作者&#xff1a;土豆娃娃文章来源&#xff1a;社区投稿 引言 作为一个MySQL数据库从业者&#xff0c;我们最常用的工具就是my…

极米RS Pro 2值得买吗?极米科技这款4K投影真实体验怎么样?

2022电商的最后一场狂欢购物节“双十二”已到来&#xff0c;许多小伙伴想趁此次机会购置一些礼物给辛苦一年的自己和家人。但礼物怎么选&#xff1f;选什么&#xff1f;又成为了困扰大家的一大问题。要说送礼物&#xff0c;无论是自己还是家人&#xff0c;实用的家电是最不容易…

SRv6----控制平面

学习了SRv6----报文转发流程后&#xff0c;下一步学习SRv6的控制平面及SID是如何在SRv6网内传递学习的。 首先回顾一下回顾一下链路状态路由协议&#xff0c;基于Dijkstra SPF&#xff08;Shortest Path First&#xff0c;最短路径优先&#xff09;算法计算到达指定地址的最短路…

基于倾斜模型、地形DEM高程点的批量自动提取

我们在进行前期的规划分析的时候&#xff0c;总是离不开地形条件等限制性因素。这次分享一个小的操作技巧&#xff0c;利用倾斜模型、DEM数据批量自动提取高程点&#xff0c;用来计算坡度、坡向、填挖方、流域分析等等。 分享一下在图新地球工具软件基于倾斜模型、地形DEM如何…

华为数字化转型之道 实践篇 第六章 数字化重构业务运作模式【进行中】

第六章 数字化重构业务运作模式 数字化转型从企业业务战略出发,通过数字化手段来重构核心业务运作模式,以实现客户交易更简单、内部作业更高效、运营管理更便捷。 6.1 业务运作模式重构是数字化转型的核心 利用数字化技术创新业务运作模式,通过重构业务流程提升企业运作效…

【openGauss/MogDB的uncommitted xmin问题解决】

一、问题现象 在测试openGauss/MogDB的时候&#xff0c;发现主库查询snapshot.tables_snap_timestamp这个表的时候&#xff0c;一select *&#xff0c;数据库就宕机&#xff0c;而备库是正常的。因为是测试环境不存在数据量太多的情况。所以最开始初步怀疑有数据页损坏了。 …

项目中less常用的一些东西

一、less简介 LESSCSS是一种动态样式语言&#xff0c;简称LESS&#xff0c;属于CSS预处理语言的一种&#xff0c;它使用类似CSS的语法&#xff0c;为CSS赋予了动态语言的特性&#xff0c;如变量、继承、运算、函数等&#xff0c;更方便CSS的编写和维护 LESS可以在多种语言、环…

Serverless初探

文中插图来自极客时间 今天听了市场部门分享的serverless, 打算用自己的话总结一下。 一般来说&#xff0c;每一个网络应用背后的原型都是&#xff1a;客户端服务端&#xff0c;通过相互传递消息&#xff08;发起请求&#xff0c;返回响应&#xff09; 从研发体系角度看&…

L2聚宽量化交易系统怎样实现股票量化策略?

L2聚宽量化交易系统怎样实现股票量化策略呢&#xff1f;说到这个问题&#xff0c;首先大家先想想&#xff0c;我们进行股票量化投资无非就是为了更高效的把握股票盈利的机会&#xff0c;但是往往在量化过程中&#xff0c;对聚宽量化交易系统的操作不了解&#xff0c;减少了自己…

ChatGPT可以一本正经的胡说八道,其他AI可以吗?

目录 1.ChatGPT是什么&#xff1f; 2.它是哪个公司开发的&#xff1f; 3.TA会做什么&#xff1f; 写文章 写代码 聊天 4.总结 1.ChatGPT是什么&#xff1f; ChatGPT是由人工智能实验室OpenAI上线的一款由 聊天机器人模型新模型&#xff0c;暂时网页版允许用户免费使用&…

树莓派下载及安装PyCharm软件

PyCharm 有专业版和社区版。专业版的功能更全&#xff0c;但是要收费&#xff0c;社区版是免费的&#xff0c;所以推荐下载这个版本。 通过点击这个链接:https://www.jetbrains.com/pycharm/download/#sectionlinux下载 Pycharm软件。 注意我们要下载的是 Linux 版本的软件。 …