您现在的位置是:首页 > 技术教程 正文

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

admin 阅读: 2024-03-31
后台-插件-广告管理-内容页头部广告(手机)

目录

前言

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

压缩上传图片


前言

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

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

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

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

  1. // 上传图片大小及格式限制
  2. export function restrictionPic(file) {
  3. // 定义上传图片大小需小于2MB
  4. const isLt2M = file.size / 1024 / 1024 < 2;
  5. if (!isLt2M) {
  6. ElMessage.error("上传头像图片大小不能超过 2MB!");
  7. return isLt2M;
  8. }
  9. // 定义上传图片格式,
  10. const types = ["image/jpg", "image/png"];
  11. const isType = types.includes(file.type);
  12. if (!isType) {
  13. ElMessage.error("上传头像图片格式不正确!");
  14. return isType;
  15. }
  16. }

压缩上传图片

用到的api:

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

  1. //读取文件的方法
  2. const fileToDataURL = (file) => {
  3. return new Promise((resolve) => {
  4. const reader = new FileReader()
  5. reader.onloadend = (e) => resolve(e.target.result)
  6. reader.readAsDataURL(file)
  7. })
  8. }

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

  1. //文件转成图片流
  2. const dataURLToImage = (dataURL) => {
  3. return new Promise((resolve) => {
  4. const img = new Image()
  5. img.onload = () => resolve(img)
  6. img.src = dataURL
  7. })
  8. }

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

  1. // 压缩图片函数,接收一个文件和压缩质量参数
  2. export function compressPic(file, quality) {
  3. var qualitys = 0.52
  4. // 根据文件大小设置不同的默认压缩质量
  5. if (parseInt((file.size / 1024).toFixed(2)) < 1024) {
  6. qualitys = 0.85
  7. }
  8. if (5 * 1024 < parseInt((file.size / 1024).toFixed(2))) {
  9. qualitys = 0.92
  10. }
  11. if (quality) qualitys = quality
  12. // 如果上传的是多个文件,递归处理每个文件
  13. if (file[0]) {
  14. return Promise.all(Array.from(file).map(e => this.compressPic(e, qualitys)))
  15. } else {
  16. return new Promise((resolve) => {
  17. // 如果图片大小小于300KB,直接返回原始图片数据
  18. if ((file.size / 1024).toFixed(2) < 300) {
  19. resolve({
  20. file: file
  21. })
  22. } else {
  23. // 创建FileReader对象,异步读取存储在客户端上的文件内容
  24. const reader = new FileReader()
  25. // 读取操作完成时触发该事件,使用格式(必须将接收到的数据从onload发送到其他函数):reader.onload = e => {}
  26. reader.onload = ({
  27. target: {
  28. result: src
  29. }
  30. }) => {
  31. //创建img元素
  32. const image = new Image()
  33. // 图片加载完成后异步执行,当image的src发生改变,浏览器就会跑去加载这个src里的资源,这个操作是异步的。
  34. image.onload = async () => {
  35. // 创建一个新的画布元素和上下文,用于绘制压缩后的图片
  36. const canvas = document.createElement('canvas')
  37. const context = canvas.getContext('2d')
  38. // 计算目标图片的宽度和高度,以适应最大宽度和高度的要求
  39. var targetWidth = image.width
  40. var targetHeight = image.height
  41. var maxWidth = 800
  42. var maxHeight = 800
  43. // 缩放图片尺寸以适应最大宽度和高度
  44. if (targetWidth > maxWidth || targetHeight > maxHeight) {
  45. const scaleFactor = Math.min(maxWidth / targetWidth, maxHeight / targetHeight);
  46. targetWidth *= scaleFactor;
  47. targetHeight *= scaleFactor;
  48. }
  49. // 设置画布的尺寸
  50. canvas.width = targetWidth
  51. canvas.height = targetHeight
  52. // 清空画布并在画布上绘制压缩后的图片
  53. context.clearRect(0, 0, targetWidth, targetHeight)
  54. context.drawImage(image, 0, 0, targetWidth, targetHeight)
  55. // 将压缩后的图片数据转换为 data URI。可以使用 type 参数其类型,默认为 PNG 格式。qualitys越小,文件体积越小
  56. const canvasURL = canvas.toDataURL(file.type, qualitys)
  57. // 解码 data URI,获取图片的二进制数据。atob:是ascii to binary,用于将ascii码解析成binary数据,即Base64的解码过程。
  58. const buffer = atob(canvasURL.split(',')[1])
  59. let length = buffer.length
  60. //创建一个 Uint8Array 类型的向量,用于存储图片的二进制数据
  61. const bufferArray = new Uint8Array(new ArrayBuffer(length))
  62. while (length--) {
  63. bufferArray[length] = buffer.charCodeAt(length)
  64. }
  65. // 创建一个压缩后的文件对象
  66. const miniFile = new File([bufferArray], file.name, {
  67. type: file.type
  68. })
  69. // 解析压缩后的文件对象
  70. resolve({
  71. file: miniFile,
  72. origin: file,
  73. beforeSrc: src,
  74. afterSrc: canvasURL,
  75. beforeKB: Number((file.size / 1024).toFixed(2)),
  76. afterKB: Number((miniFile.size / 1024).toFixed(2))
  77. })
  78. }
  79. // 设置图片的 src,触发图片加载
  80. image.src = src
  81. }
  82. // 读取文件内容,并在读取完成后触发 onload 事件
  83. reader.readAsDataURL(file)
  84. }
  85. })
  86. }
  87. }

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

标签:
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

在线投稿:投稿 站长QQ:1888636

后台-插件-广告管理-内容页尾部广告(手机)
关注我们

扫一扫关注我们,了解最新精彩内容

搜索