前端图片压缩解决办法

这篇具有很好参考价值的文章主要介绍了前端图片压缩解决办法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

问题产生背景

在某一h5的项目,要求上传的图片格式为 base64 , 问题是用户上传的图片基本都在MB 级别,转base64 以后,图片的体积会增大30%以上,随着图片的体积增加,转换的base64 格式文件体积越大,如果此时前端不对用户上传的图片体积进行压缩,可能会导致服务器压力过大,从而崩溃;

解决办法

1、使用纯 js 解决

解决思路:
1、通过 input 文件选择框拿到要上传的图片文件file
2、FileReader.readAsDataURL() 读取 file 内容。完成后 result 属性中将包含一个 data: URL格式的 Base64字符串以表示所读取文件的内容。
3、创建一个 img 标签,将 FileReader 对象返回的 base64 格式 url 给到一个 img 标签
4、img.onload() 函数中获取图片的尺寸,再通过 canvas.drawImage() 绘制图像,设置尺寸或者图像的质量等
canvas.toDataURL(file.type, quality) 设置图像的质量,将 canvas 转换为图片 base64 格式
代码如下所示:

compressImg(file) {
    const reader = new FileReader();
        // readAsDataURL 方法会读取指定的 Blob 或 File 对象。读取操作完成的时候,readyState 会变成已完成DONE,并触发 loadend (en-US) 事件,
        // 同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。
        reader.readAsDataURL(file);
        reader.onload = () => {
          const img = new Image();
          img.src = reader.result;
          img.onload = () => {
            // 图片的宽高
            const w = img.width;
            const h = img.height;
            const canvas = document.createElement("canvas");
            // canvas对图片进行裁剪,这里设置为图片的原始尺寸
            canvas.width = w;
            canvas.height = h;
            const ctx = canvas.getContext("2d");
            // canvas中,png转jpg会变黑底,所以先给canvas铺一张白底
            ctx.fillStyle = "#fff";
            // fillRect()方法绘制一个填充了内容的矩形,这个矩形的开始点(左上点)在
            // (x, y) ,它的宽度和高度分别由width 和 height 确定,填充样式由当前的fillStyle 决定。
            ctx.fillRect(0, 0, canvas.width, canvas.height);
            // 绘制图像
            ctx.drawImage(img, 0, 0, w, h);
            // canvas转图片达到图片压缩效果
            // 返回一个包含图片展示的 data URI base64 在指定图片格式为 image/jpeg 或 image/webp的情况下,
            // 可以从 0 到 1 的区间内选择图片的质量。如果超出取值范围,将会使用默认值 0.92。其他参数会被忽略。
            const dataUrl = canvas.toDataURL("image/jpeg", 0.8);
            // base64格式文件转成Blob文件格式
            return blobFile = dataURLtoBlob(dataUrl);
            // 拿到这个blobFile文件就可以上传给服务端
            console.log("压缩后的file----------", blobFile);
          };
        };
}
    // canvas生成的格式为base64,如果需要Blob格式可按如下进行转化
    dataURLtoBlob(dataurl) {
      const arr = dataurl.split(","),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]);
      let n = bstr.length;
      const u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new Blob([u8arr], { type: mime });
    },

使用以上方法存在缺点:

  • 压缩后的格式只能是 jpeg 格式,如果需要其他格式的可能需要优化或者用别的方法

2、插件 js-image-compressor

在使用中,我们可以根据自身需求自定义配置压缩比(quality)、输出图片类型(mimeType)、宽(width)、高(height)、最大宽(maxWidth)、最大高(maxHeight)、最小宽(minWidth)、最大高(minHeight)、png转jpeg阈值(convertSize)、是否矫正jpeg方向(redressOrientation)和是否宽松模式(loose)。
● 是否矫正jpeg方向(redressOrientation),jpeg 格式图片在某些iOS浏览器会按其方向呈现图像,这个选项可以控制恢复初始方向,默认为 true;
● 是否宽松模式(loose)、的意思是控制当压缩的图片 size 大于源图片,输出源图片,否则输出压缩后图片,默认是 true。
以下是标准配置:

var options = {
  file: file,
  quality: 0.6,
  mimeType: 'image/jpeg',
  maxWidth: 2000,
  maxHeight: 2000,
  width: 1000,
  height: 1000,
  minWidth: 500,
  minHeight: 500,
  convertSize: Infinity,
  loose: true,
  redressOrientation: true,
  // 压缩前回调
  beforeCompress: function (result) {
    console.log('压缩之前图片尺寸大小: ', result.size);
    console.log('mime 类型: ', result.type);
  },
  // 压缩成功回调
  success: function (result) {
    console.log('压缩之后图片尺寸大小: ', result.size);
    console.log('mime 类型: ', result.type);
    console.log('实际压缩率: ', ((file.size - result.size) / file.size * 100).toFixed(2) + '%');
  },
  // 发生错误
  error: function (msg) {
    console.error(msg);
  }
};
new ImageCompressor(options);

以上就是插件式的解决办法,更详细的文档,可以在 gitbhub 的官方文档上查看;插件式解决办法已经在项目中实践,推荐大家使用~~

写在最后

以上提供的插件式解决办法已经在项目中实践,但是存在的问题是,插件控制的压缩率和实际的压缩率有一定的出入(不同格式的图片出入有一定差异),因此压缩率不好严格控制,有更好解决办法的朋友欢迎评论区交流;

🥂(❁´◡`❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞文章来源地址https://www.toymoban.com/news/detail-622099.html

到了这里,关于前端图片压缩解决办法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前端使用 xlsx.js 工具读取 excel 遇到时间日期少 43 秒的解决办法

    在使用 xlsx 读取 excel 的时间格式的数据时,如 ‘2023-11-30’,‘2023/11/30’ ,默认会读取一串数字字符串,如:‘45260’,此时需要在 read 的时候传入一个配置项: 此时拿到的是标准的时间格式 :‘Wed Nov 29 2023 23:59:17 GMT+0800(中国标准时间)’ ,这个时间格式是带时区的,有没

    2024年02月04日
    浏览(37)
  • springboot 出现 Cannot resolve MVC View ‘index‘ 问题解决办法,前后端不分离项目前端文件存放位置,已经如何访问

    简介:本文讲解,在springboot不分离的项目中,前端的文件存放的位置,和Cannot resolve MVC View ‘index‘ 这个报错怎么处理。 我们需要把 html 相关的页面放在 resource 的 templates 的下面,然后 js,css 相关的文件需要放在 static 下面 我现在想要访问这个 index.html ,需要注意的是 @Con

    2024年04月12日
    浏览(34)
  • Microsoft Visio 画图遇到的问题及解决办法

    这条虚线是用来分页的,对画图没有影响,但可能新手会想要去掉它,方法如下: 在编辑首页中点击打开主菜单栏中的“视图”选项,然后在弹出来的窗口中点击取消打勾“分页符”选项。然后就可以看到编辑页面中的虚线成功消失啦。 如果想要在画布中画出一条虚线,只

    2024年02月06日
    浏览(36)
  • 路由器升级可能遇到的问题及解决办法

    一、出现乱码 拿出路由器,通电后通过Console口连上去,发现超级屏幕出现了一些乱码,会不会是Consol口坏了?如果出现Console口坏了,一般会在超级终端屏幕上不断输出很多的乱码,回车后出现乱码,可能是每秒传输速率不对,将默认值9600更换为l15200,路由器启动成功,路由

    2024年02月05日
    浏览(27)
  • 微信小程序picker组件遇到的问题以及解决办法

    先来看一下官方文档中picker的基本概念: 从底部弹起的滚动选择器,现支持三种选择器,通过mode来区分,分别是普通选择器,时间选择器,日期选择器,默认是普通选择器。 重要属性 range: 选取范围,数据类型为Array / Object Array,mode为 普通选择器 时,range 有效; value:

    2024年02月11日
    浏览(37)
  • IDEA遇到Cannot resolve symbol问题的解决办法

    以下列出了多种可能造成Cannot resolve symbol问题的情况, 可以根据自己的问题进行选择设置 解决: 在idea中找到File – Project Structure – Project SDK, 然后选择自己安装好的JDK 解决: 打开File – Setting – 直接搜索Maven, 然后设置Maven home path(自己的Maven安装路径) 如下图的位置, 清除缓存后

    2024年02月15日
    浏览(35)
  • 安装opencv-python遇到的问题及解决办法

           由于本人是小白,课程作业为不限软件不限语言进行横缝检测,想通过opencv进行相应的图片处理,本文是在安装导入过程中遇到的问题及解决办法,谨以此文感谢我实验室大佬。 环境:anaconda,python3.8, PyCharm2020 首先是我在导入过程中几个参考的看起来很靠谱的文章:

    2024年02月09日
    浏览(51)
  • cocos creator 3.x遇到的一些问题和解决办法

    一、场景文件损坏问题。 现象:一次异常死机,关机重启后,场景文件(cocos creator 3.6.2创建)无法打开,涉及几天的工作,如果无法恢复,损失巨大!感觉太夸张了。 分析:认真分析了场景文件格式,是json格式(可以用visual studio code打开),层次不多,以id进行关联,尝

    2024年02月05日
    浏览(54)
  • 前段项目启动时遇到错误“digital envelope routines::unsupported“的解决办法

    出现这个错误是因为 node.js V17版本中最近发布的OpenSSL3.0,V17后的版本可以尝试启用legacy OpenSSL provider来解决这个问题

    2024年04月25日
    浏览(23)
  • Tauri发送网络请求系列,接口请求封装并遇到的问题解决办法

    接口请求处理 项目中没有使用 axios 等前端 HTTP 请求库,使用的是 Tauri 内置的 fetch 方法,但该方法使用比较简单,没有请求拦截器或响应拦截器相关配置,所以我们有必要在此基础上做下二次封装。  红框选中的内容是必须改的,不然会发生跨域: 新建  utils/http.ts  文件

    2024年02月14日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包