【vue3】前端上传图片的格式大小限制和压缩

目录

前言

对上传图片进行格式大小限制

压缩上传图片


前言

上篇文章中研究了如何使用双token机制,在此篇中就暴露了一些问题:当accesstoken过期后,直到拿到最终想要得到的数据,期间需要经历三次请求——第一次请求,拿到accesstoken过期的消息——第二次携带refreshtoken发起请求,刷新了accesstoken——第三次携带新的accesstoken发起请求,拿到数据。在这个过程中会出现如下报错:

 无法加载响应数据:No data found for resource with given identifier.

在测试了一系列的请求之后,发现问题可能是该次请求携带的请求信息过大。因为我们出现问题的请求是前端上传图片到服务端获取图片链接。此时,前端能想到的优化方案是限制用户上传图片的大小和格式,并且对上传图片进行压缩。

对上传图片进行格式大小限制

// 上传图片大小及格式限制
export function restrictionPic(file) {
  // 定义上传图片大小需小于2MB
  const isLt2M = file.size / 1024 / 1024 < 2;
  if (!isLt2M) {
    ElMessage.error("上传头像图片大小不能超过 2MB!");
    return isLt2M;
  }
  // 定义上传图片格式,
  const types = ["image/jpg", "image/png"];
  const isType = types.includes(file.type);
  if (!isType) {
    ElMessage.error("上传头像图片格式不正确!");
    return isType;
  }
}

压缩上传图片

用到的api:

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

//读取文件的方法
const fileToDataURL = (file) => {
  return new Promise((resolve) => {
    const reader = new FileReader()
    reader.onloadend = (e) => resolve(e.target.result)
    reader.readAsDataURL(file)
  })
}

Image()Image()函数将会创建一个新的HTMLImageElement实例,它的功能等价于 ​​​​​document.createElement('img')。

//文件转成图片流
const dataURLToImage = (dataURL) => {
  return new Promise((resolve) => {
    const img = new Image()
    img.onload = () => resolve(img)
    img.src = dataURL
  })
}

​​​​​canvascanvas是一个可以使用脚本 (通常为JavaScript) 来绘制图形的 HTML元素。例如,它可以用于绘制图表、制作图片构图或者制作简单的动画。

// 压缩图片函数,接收一个文件和压缩质量参数
export function compressPic(file, quality) {
  var qualitys = 0.52

  // 根据文件大小设置不同的默认压缩质量
  if (parseInt((file.size / 1024).toFixed(2)) < 1024) {
    qualitys = 0.85
  }
  if (5 * 1024 < parseInt((file.size / 1024).toFixed(2))) {
    qualitys = 0.92
  }
  if (quality) qualitys = quality

  // 如果上传的是多个文件,递归处理每个文件
  if (file[0]) {
    return Promise.all(Array.from(file).map(e => this.compressPic(e, qualitys)))
  } else {
    return new Promise((resolve) => {
      // 如果图片大小小于300KB,直接返回原始图片数据
      if ((file.size / 1024).toFixed(2) < 300) {
        resolve({
          file: file
        })
      } else {
        // 创建FileReader对象,异步读取存储在客户端上的文件内容
        const reader = new FileReader()
        // 读取操作完成时触发该事件,使用格式(必须将接收到的数据从onload发送到其他函数):reader.onload = e => {}
        reader.onload = ({
          target: {
            result: src
          }
        }) => {
          //创建img元素
          const image = new Image()
          // 图片加载完成后异步执行,当image的src发生改变,浏览器就会跑去加载这个src里的资源,这个操作是异步的。
          image.onload = async () => {
            // 创建一个新的画布元素和上下文,用于绘制压缩后的图片
            const canvas = document.createElement('canvas')
            const context = canvas.getContext('2d')
            // 计算目标图片的宽度和高度,以适应最大宽度和高度的要求
            var targetWidth = image.width
            var targetHeight = image.height
            var maxWidth = 800
            var maxHeight = 800
            // 缩放图片尺寸以适应最大宽度和高度
            if (targetWidth > maxWidth || targetHeight > maxHeight) {
              const scaleFactor = Math.min(maxWidth / targetWidth, maxHeight / targetHeight);
              targetWidth *= scaleFactor;
              targetHeight *= scaleFactor;
            }
            // 设置画布的尺寸
            canvas.width = targetWidth
            canvas.height = targetHeight
            // 清空画布并在画布上绘制压缩后的图片
            context.clearRect(0, 0, targetWidth, targetHeight)
            context.drawImage(image, 0, 0, targetWidth, targetHeight)
            // 将压缩后的图片数据转换为 data URI。可以使用 type 参数其类型,默认为 PNG 格式。qualitys越小,文件体积越小
            const canvasURL = canvas.toDataURL(file.type, qualitys)
            // 解码 data URI,获取图片的二进制数据。atob:是ascii to binary,用于将ascii码解析成binary数据,即Base64的解码过程。
            const buffer = atob(canvasURL.split(',')[1])
            let length = buffer.length
            //创建一个 Uint8Array 类型的向量,用于存储图片的二进制数据
            const bufferArray = new Uint8Array(new ArrayBuffer(length))
            while (length--) {
              bufferArray[length] = buffer.charCodeAt(length)
            }
            // 创建一个压缩后的文件对象
            const miniFile = new File([bufferArray], file.name, {
              type: file.type
            })

            // 解析压缩后的文件对象
            resolve({
              file: miniFile,
              origin: file,
              beforeSrc: src,
              afterSrc: canvasURL,
              beforeKB: Number((file.size / 1024).toFixed(2)),
              afterKB: Number((miniFile.size / 1024).toFixed(2))
            })
          }
          // 设置图片的 src,触发图片加载
          image.src = src
        }
        // 读取文件内容,并在读取完成后触发 onload 事件
        reader.readAsDataURL(file)
      }
    })
  }
}

参考文章:前端图片最优化压缩方案

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
分片与并发结合 将一个大文件分割成多块 并发上传 极大地提高大文件的上传速度 当网络问题导致传输错误时 只需要重传出错分片 而不是整个文件 另外分片传输能够更加实时的跟踪上传进度 预览 压缩 支持常用图片格式jpg jpeg gif bmp png预览与压缩 节省网络数据传输 解析jpeg中的meta信息 对于各种orientation做了正确的处理 同时压缩后上传保留图片的所有原始meta数据 多途径添加文件 支持文件多选 类型过滤 拖拽 文件&文件夹 图片粘贴功能 粘贴功能主要体现在当有图片数据在剪切板中时(截屏工具如QQ Ctrl + ALT + A 网页中右击图片点击复制) Ctrl + V便可添加此图片文件 HTML5 & FLASH 兼容主流浏览器 接口一致 实现了两套运行时支持 用户无需关心内部用了什么内核 同时Flash部分没有做任何UI相关的工作 方便不关心flash的用户扩展和自定义业务需求 MD5秒传 当文件体积大 量比较多时 支持上传前做文件md5值验证 一致则可直接跳过 如果服务端与前端统一修改算法 取段md5 可大大提升验证性能 耗时在20ms左右 易扩展 可拆分 采用可拆分机制 将各个功能独立成了小组件 可自由搭配 采用AMD规范组织代码 清晰明了 方便高级玩家扩展 ">分片与并发结合 将一个大文件分割成多块 并发上传 极大地提高大文件的上传速度 当网络问题导致传输错误时 只需要重传出错分片 而不是整个文件 另外分片传输能够更加实时的跟踪上传进度 预览 压缩 支持常 [更多]
Vue中,可以使用一些库来实现图片和视频上传前压缩大小的功能。下面我将分别介绍两种情况的解决方案。 1. 图片上传前压缩大小: 可以使用`vue-image-compressor`库来实现图片上传前的压缩。首先,安装该库: ```bash npm install vue-image-compressor ``` 然后,在需要进行图片上传的组件中,导入并注册该库: ```javascript import VueImageCompressor from 'vue-image-compressor'; export default { components: { VueImageCompressor }, // ... } ``` 接下来,在模板中使用`vue-image-compressor`组件,设置相关属性来进行图片压缩: ```html <template> <div> <vue-image-compressor ref="compressor" :max-width="800" :max-height="600"></vue-image-compressor> <input type="file" @change="compressImage"> </div> </template> <script> export default { methods: { compressImage(event) { const file = event.target.files[0]; this.$refs.compressor.compress(file) .then(compressedImage => { // 压缩后的图片对象 console.log(compressedImage); // 在这里进行图片上传操作 }) .catch(error => { console.error(error); }); } } } </script> ``` 在上述代码中,`max-width`和`max-height`属性用于设置压缩后的图片的最大宽度和高度。通过`this.$refs.compressor.compress(file)`方法来进行图片压缩,返回的`compressedImage`即是压缩后的图片对象,可以在该对象中获取到压缩后的图片数据,然后进行上传操作。 2. 视频上传前压缩大小: 对于视频的压缩,可以使用`vue-video-compressor`库。首先,安装该库: ```bash npm install vue-video-compressor ``` 然后,在需要进行视频上传的组件中,导入并注册该库: ```javascript import VueVideoCompressor from 'vue-video-compressor'; export default { components: { VueVideoCompressor }, // ... } ``` 接下来,在模板中使用`vue-video-compressor`组件,设置相关属性来进行视频压缩: ```html <template> <div> <vue-video-compressor ref="compressor" :max-size="10"></vue-video-compressor> <input type="file" @change="compressVideo"> </div> </template> <script> export default { methods: { compressVideo(event) { const file = event.target.files[0]; this.$refs.compressor.compress(file) .then(compressedVideo => { // 压缩后的视频对象 console.log(compressedVideo); // 在这里进行视频上传操作 }) .catch(error => { console.error(error); }); } } } </script> ``` 在上述代码中,`max-size`属性用于设置压缩后的视频文件大小的上限(单位为MB)。通过`this.$refs.compressor.compress(file)`方法来进行视频压缩,返回的`compressedVideo`即是压缩后的视频对象,可以在该对象中获取到压缩后的视频数据,然后进行上传操作。 以上就是在Vue中实现图片和视频上传前压缩大小的简单示例,希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值