TypechoJoeTheme

香草物语

统计
登录
用户名
密码
/
注册
用户名
邮箱
输入密码
确认密码

若依系统上传图片压缩

Laughing博主
2024-03-22
/
0 评论
/
129 阅读
/
1696 个字
/
百度已收录
03/22
本文最后更新于2024年03月22日,已超过37天没有更新。如果文章内容或图片资源失效,请留言反馈,我会及时处理,谢谢!

虽然标题里面有若依,实际上所有的Vue项目都能够适用的。

最近基于若依系统做点东西,若依系统本身封装了一个图片上传组件ImageUpload,但是这个组件对我来说不太适用,最主要的问题就是这个组件是自动上传的,这样就会导致我们业务数据跟附件无法做到同步,比如我们新增一个单据,点了上传图片,此时图片已经上传到服务器,但是我并没有保存单据,这样就造成了部分垃圾数据。当然不是说不能处理,只是来说更加麻烦。

先来说下我们目前做的功能需求吧:

  1. 基于ElementUI的el-upload上传图片
  2. 为了减少图片占用的空间(目前基于阿里云OSS,这个后期介绍),我们在前端上传图片之前在不影响图片展示质量的前提下,对图片进行压缩
  3. 表单数据与图片文件同步上传
  4. 可以单张图片上传也可以同时上传多张图片(以下我们以多张图片上传来说明)

壹、提取图片压缩公共方法

ruoyi.js公共方法中,封装图片压缩方法

/** 图片压缩,默认同比例压缩
 *  @param {Object} fileObj
 *  图片对象
 *  回调函数有一个参数,base64的字符串数据
 */
export function compress(fileObj, callback) {
  // console.log('压缩前文件大小', fileObj.size)
  try {
    const image = new Image()
    image.src = URL.createObjectURL(fileObj)
    image.onload = function () {
      const that = this
      // 默认按比例压缩
      let w = that.width
      let h = that.height
      const scale = w / h
      w = fileObj.width || w
      h = fileObj.height || (w / scale)
      let quality = 0.5 // 默认图片质量为0.7
      // 生成canvas
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      // 创建属性节点
      const anw = document.createAttribute('width')
      anw.nodeValue = w
      const anh = document.createAttribute('height')
      anh.nodeValue = h
      canvas.setAttributeNode(anw)
      canvas.setAttributeNode(anh)
      ctx.drawImage(that, 0, 0, w, h)
      // 图像质量
      if (fileObj.quality && fileObj.quality <= 1 && fileObj.quality > 0) {
        quality = fileObj.quality
      }
      // quality值越小,所绘制出的图像越模糊
      const data = canvas.toDataURL('image/jpeg', quality)
      // 压缩完成执行回调
      const newFile = convertBase64UrlToBlob(data)
      callback(newFile)
      // console.log('压缩后文件信息', newFile)
    }
  } catch (e) {
    console.log('压缩失败!')
  }
}

// Base64 => 二进制(Blob)
function convertBase64UrlToBlob(urlData) {
  // 去掉url的头,并转换为byte
  const bytes = window.atob(urlData.split(',')[1])
  // 处理异常,将ascii码小于0的转换为大于0
  const ab = new ArrayBuffer(bytes.length)
  const ia = new Uint8Array(ab)
  for (let i = 0; i < bytes.length; i++) {
    ia[i] = bytes.charCodeAt(i)
  }
  return new Blob([ab], {type: 'image/png'})
}

main.js中挂载公共方法,方便在后面使用

Vue.prototype.compress = compress

贰、页面增加上传图片功能

在表单中,增加上传图片功能

<el-upload action="#" list-type="picture-card" :auto-upload="false" multiple :headers="headers"
                           ref="carPhotoListRef" :on-preview="handlePictureCardPreview" :on-remove="handleRemove"
                           :on-change="handleChange" :file-list="imageFileList"
                           :disabled="form.inquiryStatus !== 'inquirying'"
                           :class="{ hide: form.inquiryStatus !== 'inquirying' }"
                           accept="image/bmp,image/jpg,image/png,image/svg,image/psd,image/webp,image/jpeg">
                  <i class="el-icon-plus"></i>
                </el-upload>
                <el-dialog :visible.sync="dialogImageVisible" :append-to-body="true">
                  <img width="100%" :src="dialogImageUrl" alt=""/>
                </el-dialog>

因为我们要手工上传图片,所以需要对el-upload的属性进行配置

action因为我们要收工上传,所以action需要设置成#

auto-upload设置成false禁止自动上传

headers是基于若依的认证,传递头部信息的

on-preview预览图片

on-remove删除图片同步处理我们后端绑定数据

on-change图片改变的钩子,因为我们要手工上传图片,因此通过这个钩子完成图片的压缩

其他的一些属性基本设置图片预览,限制上传图片类型的,按需设置即可。

data里面主要设置图片预览、绑定图片列表等属性

data() {
    return {
      headers: {
        Authorization: "Bearer " + getToken()
      },
      //预览图片窗口是否可见
      dialogImageVisible: false,
      //预览图片Url
      dialogImageUrl: null,
      imageFileList: [],
    }
  }

method方法如下

//删除图片
    handleRemove(file, fileList) {
      this.imageFileList = fileList
      if (this.form.carPhotoList) {
        let index = -1
        for (let i = 0; i < this.form.carPhotoList.length; i++) {
          if (this.form.carPhotoList[i].photoId === file.photoId) {
            index = i
          }
        }
        if (index !== -1) {
          this.$delete(this.form.carPhotoList, index)
        }
      }
    },
    //图片改变
    handleChange(file, fileList) {
      let that = this
      // 调用自定义的压缩方法
      compress(file.raw, function (val) {
        // 图片格式: blob => file
        let newFile = new window.File([val], file.name, {type: file.raw.type});
        // 新增属性(file)并赋值
        let fileObj = {}
        fileObj.raw = newFile
        fileObj.name = file.name
        fileObj.uid = file.uid;
        fileObj.url = URL.createObjectURL(file.raw);
        that.imageFileList.push(fileObj)
      })

      // this.imageFileList = fileList
    },
    //预览图片
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url
      this.dialogImageVisible = true
    },

实现图片压缩主要是通过on-change钩子,选择图片后,通过on-change钩子调用handleChange方法,我们拿到图片文件后,调用compress方法,通过回调函数,将压缩后的图片绑定到imageFileList

表单保存

/** 提交按钮 */
    submitForm() {
      if (this.imageFileList.length <= 0) {
        this.msgInfo('请上传图片')
        return
      }
      const loading = this.$loading({
        lock: true,//lock的修改符--默认是false
        text: "保存中",//显示在加载图标下方的加载文案
        spinner: "el-icon-loading",//自定义加载图标类名
        background: "rgba(0, 0, 0, 0.7)",//遮罩层颜色
        target: document.querySelector("#table")//loadin覆盖的dom元素节点
      })
      this.$refs["form"].validate(valid => {
        if (valid) {
          let formData = new FormData()
          this.imageFileList.forEach(file => {
            formData.append("imageFileList", file.raw)// 图片列表
          })
          formData.append("form", JSON.stringify(this.form))//表单
          if (this.form.inquiryId != null) {
            updateInquiry(formData).then(response => {
              loading.close()
              this.msgSuccess("修改成功")
              this.open = false
              this.getList()
            }).catch(error => {
              loading.close()
            })
          } else {
            addInquiry(formData).then(response => {
              loading.close()
              this.msgSuccess("新增成功")
              this.open = false
              this.getList()
            }).catch(error => {
              loading.close()
            })
          }
        } else {
          loading.close()
        }
      })
    },

在表单保存方法中,我们通过FormData将图片文件与表单数据,一起保存。

![image-20240322230941560](虽然标题里面有若依,实际上所有的Vue项目都能够适用的。

最近基于若依系统做点东西,若依系统本身封装了一个图片上传组件ImageUpload,但是这个组件对我来说不太适用,最主要的问题就是这个组件是自动上传的,这样就会导致我们业务数据跟附件无法做到同步,比如我们新增一个单据,点了上传图片,此时图片已经上传到服务器,但是我并没有保存单据,这样就造成了部分垃圾数据。当然不是说不能处理,只是来说更加麻烦。

先来说下我们目前做的功能需求吧:

  1. 基于ElementUI的el-upload上传图片
  2. 为了减少图片占用的空间(目前基于阿里云OSS,这个后期介绍),我们在前端上传图片之前在不影响图片展示质量的前提下,对图片进行压缩
  3. 表单数据与图片文件同步上传
  4. 可以单张图片上传也可以同时上传多张图片(以下我们以多张图片上传来说明)

壹、提取图片压缩公共方法

ruoyi.js公共方法中,封装图片压缩方法

/** 图片压缩,默认同比例压缩
 *  @param {Object} fileObj
 *  图片对象
 *  回调函数有一个参数,base64的字符串数据
 */
export function compress(fileObj, callback) {
  // console.log('压缩前文件大小', fileObj.size)
  try {
    const image = new Image()
    image.src = URL.createObjectURL(fileObj)
    image.onload = function () {
      const that = this
      // 默认按比例压缩
      let w = that.width
      let h = that.height
      const scale = w / h
      w = fileObj.width || w
      h = fileObj.height || (w / scale)
      let quality = 0.5 // 默认图片质量为0.7
      // 生成canvas
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      // 创建属性节点
      const anw = document.createAttribute('width')
      anw.nodeValue = w
      const anh = document.createAttribute('height')
      anh.nodeValue = h
      canvas.setAttributeNode(anw)
      canvas.setAttributeNode(anh)
      ctx.drawImage(that, 0, 0, w, h)
      // 图像质量
      if (fileObj.quality && fileObj.quality <= 1 && fileObj.quality > 0) {
        quality = fileObj.quality
      }
      // quality值越小,所绘制出的图像越模糊
      const data = canvas.toDataURL('image/jpeg', quality)
      // 压缩完成执行回调
      const newFile = convertBase64UrlToBlob(data)
      callback(newFile)
      // console.log('压缩后文件信息', newFile)
    }
  } catch (e) {
    console.log('压缩失败!')
  }
}

// Base64 => 二进制(Blob)
function convertBase64UrlToBlob(urlData) {
  // 去掉url的头,并转换为byte
  const bytes = window.atob(urlData.split(',')[1])
  // 处理异常,将ascii码小于0的转换为大于0
  const ab = new ArrayBuffer(bytes.length)
  const ia = new Uint8Array(ab)
  for (let i = 0; i < bytes.length; i++) {
    ia[i] = bytes.charCodeAt(i)
  }
  return new Blob([ab], {type: 'image/png'})
}

main.js中挂载公共方法,方便在后面使用

Vue.prototype.compress = compress

贰、页面增加上传图片功能

在表单中,增加上传图片功能

<el-upload action="#" list-type="picture-card" :auto-upload="false" multiple :headers="headers"
                           ref="carPhotoListRef" :on-preview="handlePictureCardPreview" :on-remove="handleRemove"
                           :on-change="handleChange" :file-list="imageFileList"
                           :disabled="form.inquiryStatus !== 'inquirying'"
                           :class="{ hide: form.inquiryStatus !== 'inquirying' }"
                           accept="image/bmp,image/jpg,image/png,image/svg,image/psd,image/webp,image/jpeg">
                  <i class="el-icon-plus"></i>
                </el-upload>
                <el-dialog :visible.sync="dialogImageVisible" :append-to-body="true">
                  <img width="100%" :src="dialogImageUrl" alt=""/>
                </el-dialog>

因为我们要手工上传图片,所以需要对el-upload的属性进行配置

action因为我们要收工上传,所以action需要设置成#

auto-upload设置成false禁止自动上传

headers是基于若依的认证,传递头部信息的

on-preview预览图片

on-remove删除图片同步处理我们后端绑定数据

on-change图片改变的钩子,因为我们要手工上传图片,因此通过这个钩子完成图片的压缩

其他的一些属性基本设置图片预览,限制上传图片类型的,按需设置即可。

data里面主要设置图片预览、绑定图片列表等属性

data() {
    return {
      headers: {
        Authorization: "Bearer " + getToken()
      },
      //预览图片窗口是否可见
      dialogImageVisible: false,
      //预览图片Url
      dialogImageUrl: null,
      imageFileList: [],
    }
  }

method方法如下

//删除图片
    handleRemove(file, fileList) {
      this.imageFileList = fileList
      if (this.form.carPhotoList) {
        let index = -1
        for (let i = 0; i < this.form.carPhotoList.length; i++) {
          if (this.form.carPhotoList[i].photoId === file.photoId) {
            index = i
          }
        }
        if (index !== -1) {
          this.$delete(this.form.carPhotoList, index)
        }
      }
    },
    //图片改变
    handleChange(file, fileList) {
      let that = this
      // 调用自定义的压缩方法
      compress(file.raw, function (val) {
        // 图片格式: blob => file
        let newFile = new window.File([val], file.name, {type: file.raw.type});
        // 新增属性(file)并赋值
        let fileObj = {}
        fileObj.raw = newFile
        fileObj.name = file.name
        fileObj.uid = file.uid;
        fileObj.url = URL.createObjectURL(file.raw);
        that.imageFileList.push(fileObj)
      })

      // this.imageFileList = fileList
    },
    //预览图片
    handlePictureCardPreview(file) {
      this.dialogImageUrl = file.url
      this.dialogImageVisible = true
    },

实现图片压缩主要是通过on-change钩子,选择图片后,通过on-change钩子调用handleChange方法,我们拿到图片文件后,调用compress方法,通过回调函数,将压缩后的图片绑定到imageFileList

表单保存

/** 提交按钮 */
    submitForm() {
      if (this.imageFileList.length <= 0) {
        this.msgInfo('请上传图片')
        return
      }
      const loading = this.$loading({
        lock: true,//lock的修改符--默认是false
        text: "保存中",//显示在加载图标下方的加载文案
        spinner: "el-icon-loading",//自定义加载图标类名
        background: "rgba(0, 0, 0, 0.7)",//遮罩层颜色
        target: document.querySelector("#table")//loadin覆盖的dom元素节点
      })
      this.$refs["form"].validate(valid => {
        if (valid) {
          let formData = new FormData()
          this.imageFileList.forEach(file => {
            formData.append("imageFileList", file.raw)// 图片列表
          })
          formData.append("form", JSON.stringify(this.form))//表单
          if (this.form.inquiryId != null) {
            updateInquiry(formData).then(response => {
              loading.close()
              this.msgSuccess("修改成功")
              this.open = false
              this.getList()
            }).catch(error => {
              loading.close()
            })
          } else {
            addInquiry(formData).then(response => {
              loading.close()
              this.msgSuccess("新增成功")
              this.open = false
              this.getList()
            }).catch(error => {
              loading.close()
            })
          }
        } else {
          loading.close()
        }
      })
    },

在表单保存方法中,我们通过FormData将图片文件与表单数据,一起保存。

ElementUIVue
朗读
赞(0)
赞赏
感谢您的支持,我会继续努力哒!
版权属于:

香草物语

本文链接:

https://www.xiangcaowuyu.net/web/if-uploading-images-according-to-the-system-compresses.html(转载时请注明本文出处及文章链接)

评论 (0)