Vue 图片压缩上传: element-ui + lrz
步骤
- 安装依赖包 npm install --save lrz
- 在main.js里引入import lrz from 'lrz'
- 封装 compress函数
- 封装上传组件 upload-image
- 在 vue 文件中 使用
封装 compress函数
// eslint-disable
/** @format */
// base64编码转File
export function dataURLtoFile(dataurl, filename) {
  var arr = dataurl.split(','),
    mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]),
    n = bstr.length,
    u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new File([u8arr], filename, { type: mime });
}
// main function.
export function compress(file, fileList, that, reference) {
  if (file.status != 'ready') {
    return;
  }
  let index = reference.uploadFiles.indexOf(file);
  // jpg/jpeg/bmp/gif/png
  let isJPG =
    file.raw.type === 'image/jpg' ||
    file.raw.type === 'image/jpeg' ||
    file.raw.type === 'image/png' ||
    file.raw.type === 'image/gif' ||
    file.raw.type === 'image/bmp'
  const isLt20M = file.size / 1024 / 1024 < 20;
  if (!isJPG) {
    that.$message.error('不支持的格式,请上传jpg/jpeg/bmp/gif/png格式的图片!');
    fileList.splice(fileList.indexOf(file), 1);
    return;
  }
  if (!isLt20M) {
    that.$message.error('上传图片大小不能超过 20MB!');
    fileList.splice(fileList.indexOf(file), 1);
    return;
  }
  if (isJPG & isLt20M) {
    if (isLt2M(file)) {
      // pdf不压缩
      submit(reference, file);
    } else {
      let options = {};
      lrz(file.raw, options)
        .then(rst => {
          let tempFile = dataURLtoFile(rst.base64, rst.origin.name);
          tempFile.uid = rst.origin.uid;
          reference.uploadFiles[index].raw = tempFile;
          reference.uploadFiles[index].size = rst.fileLen;
        })
        .catch(function (error) {
          // 失败时执行
          if (error) {
            // IE报错
            if (error.name == 'TypeError' && error.message == '对象不支持此操作') {
              that.$message.error('当前浏览器不支持上传大于2M的文件,请更换浏览器!');
            }
            // 图片格式问题
            else if ((error + '').indexOf('加载图片文件失败') > -1) {
              that.$message.error('系统未能识别当前上传图片,请更换!');
            }
          }
          fileList.splice(fileList.indexOf(file), 1);
        })
        .always(function () {
          //不管成功或失败都会执行
          submit(reference, file);
        });
    }
  }
}
// 判断文件大小是否小于2M
function isLt2M(file) {
  if (file.raw.type === 'application/pdf') {
    return true;
  } else {
    return file.size / 1024 / 1024 < 2;
  }
}
function submit(reference, file) {
  let submitFlag = true;
  if (reference.multiple) {
    for (let item of reference.uploadFiles) {
      if (item.status != 'ready') {
        continue;
      }
      if (!isLt2M(item)) {
        submitFlag = false;
        break;
      } else {
        submitFlag = true;
      }
    }
  } else {
    if (!isLt2M(file)) {
      submitFlag = false;
    } else {
      submitFlag = true;
    }
  }
  if (submitFlag) {
    reference.submit();
    return;
  }
}
封装上传组件upload-image
<template>
  <div class="upload-component-container">
    <div class="upload-section">
      <!-- 上传主体 -->
      <el-row>
        <el-upload
          ref="imageUploadRef"
          :headers="token"
          :action="uploadUrl"
          :auto-upload="false"
          list-type="picture-card"
          :file-list="imageList"
          :on-change="resize"
          :on-remove="handleRemove"
          :on-preview="handlePreview"
          :on-success="handleSuccess"
          :on-error="handleError"
          :on-exceed="handleExceed"
          :on-progress="handleProgress"
          :class="imageList.length >= maxCount ? 'uploaded-none':''"
          :limit="maxCount"
        >
          <div class="icon-container" v-loading="loading">
            <i class="el-icon-plus upload-icon"></i>
          </div>
        </el-upload>
      </el-row>
      <!-- 上传描述 -->
      <el-row v-if="needDesc">
        <div class="upload-text-desc" :style="descStyle">{{uploadDesc}}</div>
      </el-row>
    </div>
    <!--  查看图片 -->
    <el-dialog
      width="50%"
      :modal="modal"
      @close="imageVisible=false"
      :modal-append-to-body="false"
      :visible.sync="imageVisible"
    >
      <img width="100%" :src="dialogImageUrl" alt />
    </el-dialog>
  </div>
</template>
<script>
import { getBaseUrl, uuid as getUUId } from '@/utils/basic/' //  引入项目的api前缀
import { getToken } from '@/utils/browser' //  引入token
import { compress } from '@/utils/image/compress' //  引入上一步封装的压缩函数
import lodash from 'lodash'
export default {
  name: 'UploadImage',
  props: {
    modal: { type: Boolean, default: () => { false } },
    maxCount: { type: Number, required: true },
    uploadDesc: { type: String },
    initShowImages: { type: [Array, String], required: true },
    singleFile: { type: Boolean, default: false },
    needDesc: { type: Boolean, default: true },
    handleChange: { type: Function, required: true },
    descStyle: { type: Object, default: () => { null } }
  },
  data() {
    return {
      uploadUrl: getBaseUrl() + '/api/base/uploadImg',
      token: { Authorization: getToken(), 'X-Trace-ID': getUUId() },
      imageList: [],
      loading: false,
      imageVisible: false,
      dialogImageUrl: ''
    }
  },
  methods: {
    // 启用压缩
    resize(file, fileList) {
      compress(file, fileList, this, this.$refs.imageUploadRef)
    },
    // 上传成功
    handleSuccess(res, f, fList) {
      if (res.status === 1 && res.result.length > 0) {
        if (res.result[0].url) {
          this.imageList.push({
            url: res.result[0].url,
            // 兼容saas的初始 attachmentUrl 属性
            attachmentUrl: res.result[0].url //
          })
        } else {
          this.imageList.push({
            url: fList[0].url,
            // 兼容saas的初始 attachmentUrl 属性
            attachmentUrl: fList[0].url //
          })
        }
      }
      // 根据接收类型将结果发送到父组件
      if (this.singleFile == true) {
        this.handleChange(this.imageList[0].url)
      } else {
        this.handleChange(this.imageList)
      }
      this.loading = false
    },
    // 删除事件
    handleRemove(res) {
      this.imageList = lodash.filter(this.imageList, item => {
        if (res.response) {
          return item.url !== res.response.result[0].url
        } else {
          return item.url !== res.url
        }
      })
      // 根据接收类型将结果发送到父组件 => 单个文件
      if (this.singleFile == true) {
        this.handleChange('')
      } else {
        this.handleChange(this.imageList)
      }
      this.$forceUpdate()
    },
    // 最大数
    handleExceed() {
      this.$message({ type: 'warning', message: `最多上传${this.maxCount}张图片` })
    },
    // 上传错误
    handleError(err, file, fileList) {
      this.$message({ message: err.data.msg, type: 'error' })
    },
    // 查看图片
    handlePreview(file) {
      this.dialogImageUrl = file.url
      this.imageVisible = true
    },
    handleProgress() {
      this.loading = true
    }
  },
  mounted() {
    // case: string(logo)
    if (this.singleFile == true) {
      // 非空值
      if (this.initShowImages) {
        this.imageList.push({ url: this.initShowImages })
      } else {
        this.imageList = []
      }
    } else {
      // 列表文件
      this.imageList = this.initShowImages
    }
  },
  watch: {
    initShowImages(val) {
      // case: string(logo)
      if (this.singleFile == true) {
        // 非空值
        if (val) {
          this.imageList = [{ url: val }]
        } else {
          this.imageList = []
        }
      } else {
        // 列表文件
        this.imageList = val
      }
    }
  }
}
</script>
<style lang="scss">
.upload-component-container {
  .upload-section {
    background: #ffffff;
    border-radius: 4px;
    padding-top: 2px;
    .uploaded-none {
      .el-upload--picture-card {
        display: none;
      }
    }
    .el-upload-list--picture-card .el-upload-list__item {
      width: 60px;
      height: 60px;
    }
    .el-upload--picture-card {
      width: 60px;
      height: 60px;
      line-height: 125px;
      i {
        font-size: 20px !important;
      }
    }
    .icon-container {
      line-height: 2.5em;
      padding-top: 12px;
    }
    .el-icon-plus:before {
      // background: rgb(77, 227, 193);
      color: #000;
      border-radius: 12px;
    }
  }
  .upload-text-desc {
    font-size: 12px;
    color: #939393;
    margin-top: 4px;
    margin-bottom: 5px;
  }
}
</style>
在 vue 文件中使用
<template>
  <div class="contract-other-edit-container">
      <el-row>
        <el-col :span="12">
          <upload-image
            :modal="false"
            :maxCount="5"
            uploadDesc="格式要求:支持jpg/jpeg/bmp/gif/png格式图片,大小不超过20MB,多上传5张图片."
            :handleChange="handleUploadImage"
            :initShowImages="imageList"
          />
        </el-col>
      </el-row>
  </div>
</template>
<script>
import UploadImage from '@/components/element-ui/upload/image' // 组件的位置
export default {
  name: 'other-edit',
  components: { UploadImage },
  data() {
    return {
      imageList: []
    }
  },
  methods: {
    handleUploadImage(files) {
      this.imageList = files
    }
  }
}
</script>
Vue 图片压缩上传: element-ui + lrz的更多相关文章
- 基于vue + axios + lrz.js 微信端图片压缩上传
		业务场景 微信端项目是基于Vux + Axios构建的,关于图片上传的业务场景有以下几点需求: 1.单张图片上传(如个人头像,实名认证等业务) 2.多张图片上传(如某类工单记录) 3.上传图片时期望能 ... 
- 三款不错的图片压缩上传插件(webuploader+localResizeIMG4+LUploader)
		涉及到网页图片的交互,少不了图片的压缩上传,相关的插件有很多,相信大家都有用过,这里我就推荐三款,至于好处就仁者见仁喽: 1.名气最高的WebUploader,由Baidu FEX 团队开发,以H5为 ... 
- Html5+asp.net mvc 图片压缩上传
		在做图片上传时,大图片如果没有压缩直接上传时间会非常长,因为有的图片太大,传到服务器上再压缩太慢了,而且损耗流量. 思路是将图片抽样显示在canvas上,然后用通过canvas.toDataURL方法 ... 
- 纯原生js移动端图片压缩上传插件
		前段时间,同事又来咨询一个问题了,说手机端动不动拍照就好几M高清大图,上传服务器太慢,问问我有没有可以压缩图片并上传的js插件,当然手头上没有,别慌,我去网上搜一搜. 结果呢,呵呵...诶~又全是基于 ... 
- springMVC多图片压缩上传的实现
		首先需要在配置文件中添加配置: <!--配置文件的视图解析器,用于文件上传,其中ID是固定的:multipartResolver--> <bean id="multipar ... 
- 基于H5+ API手机相册图片压缩上传
		// 母函数 function App(){} /** * 图片压缩,默认同比例压缩 * @param {Object} path * pc端传入的路径可以为相对路径,但是在移动端上必须传入的路径是照 ... 
- 分享图片压缩上传demo,可以选择一张或多张图片也可以拍摄照片
		2016-08-05更新: 下方的代码是比较OLD的了,是通过js进行图片的剪切 旋转 再生成,效率较低. 后来又整合了一个利用native.js本地接口的压缩代码 ,链接在这 .页面中有详细的说明, ... 
- js 图片压缩上传(base64位)以及上传类型分类
		一.input file上传类型 1.指明只需要图片 <input type="file" accept='image/*'> 2.指明需要多张图片 <input ... 
- Vue directive自定义指令+canvas实现H5图片压缩上传-Base64格式
		前言 最近优化项目-手机拍照图片太大,回显速度比较慢,使用了vue的自定义指令实现H5压缩上传base64格式的图片 canvas自定义指令 Vue.directive("canvas&qu ... 
随机推荐
- 微信小程序开发部署
			一.开发准备 1,想要开发微信小程序,必须要有一个AppId,如果没有可以去注册一个. https://mp.weixin.qq.com/进入注册页面,点击上方注册. 2,点击选择“小程序”出 ... 
- echarts 实战 : 怎么处理特殊的图表数字 label ?
			所谓Label,就是在图表上面显示的那个数字. 但有的时候我们需要柱状图堆叠. 那如果我们需要所有数字都在外面,并且以 320/210/310/410/1320 这样的形式显示呢? 那么 echart ... 
- 给咱的服务器安装BBR脚本
			yum -y install wget ##ContOS Yum 安装 wget apt-get install wget ##Debian Ubuntu 安装 wget 先给咱的服务器安装wget, ... 
- JAVA集合四:比较器--类自定义排序
			参考链接: HOW2J.CN 前言 对于JAVA集合,都能够用集合的工具类Collections 提供的方法: Collections.sort(List list) Collections.sort ... 
- Java之枚举类
			有时候,变量的取值只在一个有限的集合内. 例如:pizza的大小只有小.中.大和超大这四种尺寸.当然,可以将这些尺寸分别编码为1.2.3.4或者S.M.L.X.但这样存在着一定的隐患.在变量中很有可能 ... 
- 单例模式—Java实现
			饿汉法 顾名思义,饿汉法就是在第一次引用该类的时候就创建对象实例,而不管实际是否需要创建.代码如下: 1 2 3 4 5 6 7 public class Singleton { priv ... 
- 在java中进行日期时间比较的4种方法
			1. Date.compareTo() java.util.Date提供了在Java中比较两个日期的经典方法compareTo(). 如果两个日期相等,则返回值为0. 如果Date在date参数之后, ... 
- seaborn分类数据可视化:散点图|箱型图|小提琴图|lv图|柱状图|折线图
			一.散点图stripplot( ) 与swarmplot() 1.分类散点图stripplot( ) 用法stripplot(x=None, y=None, hue=None, data=None, ... 
- jmeter 命令行模式(非GUI)运行脚本,察看结果树结果为空,解决办法;
			jmeter的bin目录下,打开命令窗口,执行jmeter -n -t jmeter脚本 -l 结果: 执行结束后,聚合报告打开结果,显示错误率100%:察看结果树中打开结果,显示无数据: 解决办法: ... 
- encode 和 decode 的使用
			txt = '我是字符串' txt_encode = txt.encode() print(txt) # 我是字符串 print(txt_encode) # b'\xe6\x88\x91\xe6\x9 ... 
