扩展element-ui el-upload组件,实现复制粘贴上传图片文件,带图片预览功能

扩展element-ui的el-upload上传组件,实现复制粘贴上传图片文件,带图片预览功能

需求说明

原业务系统中的图片上传功能经常使用,普通的添加按钮只能通过系统对话框打开本地计算机目录,
在本地文件夹中选择要上传的图片。
导致在使用业务系统过程中,截图后需要先将图片存储到本地计算机目录,再点击页面图片上传。
在重复使用该功能时会浪费过多的时间在图片保存,上传。
为了解决业务该问题,亟需对该图片上传功能进行改造,避免业务人员过多的时间浪费在图片上传操作。

图片上传

改造路线

为了简化图片上传步骤,增加直接粘贴 “粘贴板”中的图片文件,做到图片不落地,减少图片上传所需要的操作步骤。

改造前分析

通过对前端框架的分析,当前图片上传功能,采用 element-ui 组件,版本为 2.15.6
实现粘贴图片,需要监听ctrl + v 命令

开始改造

控件改造

在窗口的 el-form 控件参数中添加 @paste.native 事件,事件绑定方法名 handlePaste
也可以在其他控件中添加事件监听,看个人需求。

注意: 监听粘贴事件时,需要当前页面先获取焦点,否则无法正常监听, 可以在页面加载后调用 focus() 获取焦点

粘贴功能Js部分参考资料:https://blog.csdn.net/blue__k/article/details/125296866

<el-form
  ref="xxxx"
  @paste.native="handlePaste"
  :model="form"
  label-position="right"
  label-width="92px"
  class="page-form"
  style="width: 100%;"
>
------------------------ 分割线 ----------------------
// el-upload控件不用做任何修改,此处仅作展示
<el-upload  
  class="el-upload–picture-card"
  action=""
  :limit="12"
  ref="upload"
  list-type="picture-card"
  :on-preview="handlePictureCardPreview4"
  :before-upload="beforeAvatarUpload4"
  :on-remove="handleRemove4"
  :on-change="handleEditChange4"
  :http-request='uploadlinkmanAfter'
  :file-list="fileList"
  accept=".png,.jpg,.bmp,.jpeg"
  :class="{hide:hideUploadEdit4}"
    >
    <i slot="default" class="el-icon-plus"></i>
    <div slot="tip" class="el-upload__tip">
      只能上传(png,jpg,bmp,jpeg)图片文件,不超过10MB,只允许上传一份文件
    </div>
</el-upload>


Javascript 实现函数

/**
 * 监听粘贴操作
 */
handlePaste(e) {
  var clipboardData = e.clipboardData; // IE
  if (!clipboardData) {
      //chrome
    clipboardData = e.originalEvent.clipboardData;
  }
  var items='';
  items = (e.clipboardData || window.clipboardData).items;
  let file = null;
  if (!items || items.length === 0) {
    this.$message.error('当前浏览器不支持粘贴本地图片,请打开图片复制后再粘贴!');
    return;
  }
  // 搜索剪切板items
  for (let i = 0; i < items.length; i++) {
    // 限制上传文件类型
    if (items[i].type.indexOf('image') !== -1) {
      file = items[i].getAsFile();
      break;
    }
  }
  // 对复制黏贴的类型进行判断,若是非文件类型,比如复制黏贴的文字,则不会调用上传文件的函数
  if(file){
    // 上传到图片服务器
    xxxxx.uploadImage2OSS(file);
  }
},

遇到的问题(可以监听到粘贴事件,但没有生成缩略图)

在生成预览图的时候遇到了粘贴后的图片没有生成预览图片,跟踪到element-ui控件的源码中
先打开开发者工具,发现正常的预览图片 src 属性有 blob:http://localhost/xxxxx
由于该图片的url是本地缓存的图片文件,所以在upload控件中必然有图片缓存函数存在
继续跟踪upload控件有可能创建图片的源码,在index.vue文件第165行(仅供当前版本,其他版本可能有差异)中发现这样一行代码:file.url = URL.createObjectURL(rawFile);

handleStart(rawFile) {
  rawFile.uid = Date.now() + this.tempIndex++;
  let file = {
    status: 'ready',
    name: rawFile.name,
    size: rawFile.size,
    percentage: 0,
    uid: rawFile.uid,
    raw: rawFile
  };

  if (this.listType === 'picture-card' || this.listType === 'picture') {
    try {
      file.url = URL.createObjectURL(rawFile);
    } catch (err) {
      console.error('[Element Error][Upload]', err);
      return;
    }
  }

  this.uploadFiles.push(file);
  this.onChange(file, this.uploadFiles);
},

修改后的Javascript函数,调用upload控件中的 handleStart() 函数

/**
 * 监听粘贴操作
 */
handlePaste(e) {
  var clipboardData = e.clipboardData; // IE
  if (!clipboardData) {
      //chrome
    clipboardData = e.originalEvent.clipboardData;
  }
  var items='';
  items = (e.clipboardData || window.clipboardData).items;
  let file = null;
  if (!items || items.length === 0) {
    this.$message.error('当前浏览器不支持粘贴本地图片,请打开图片复制后再粘贴!');
    return;
  }
  // 搜索剪切板items
  for (let i = 0; i < items.length; i++) {
    // 限制上传文件类型
    if (items[i].type.indexOf('image') !== -1) {
      file = items[i].getAsFile();
      break;
    }
  }
  // 对复制黏贴的类型进行判断,若是非文件类型,比如复制黏贴的文字,则不会调用上传文件的函数
  if(file){
    // 上传到图片服务器
    xxxxx.uploadImage2OSS(file);
    // 生成预览图
    this.$refs.upload.handleStart(file);
  }
},

最终实现的效果图

图片上传效果图

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Element-UIel-upload 组件本身并不支持分片上传,但是我们可以通过使用第三方库来实现分片上传的功能。 一种常见的方案是使用 axios 库来进行文件上传,并在上传时使用 axios 的分片上传功能。axios 库已经内置了分片上传的支持,我们可以使用 axios 的 `axios.post` 方法来上传文件,并使用 `onUploadProgress` 方法来监听上传进度。 首先,我们需要在项目中安装 axios 和 element-ui: ``` npm install axios element-ui --save ``` 然后,我们可以在组件中使用 el-upload 组件来上传文件,如下所示: ```html <template> <el-upload class="upload-demo" ref="upload" :action="uploadUrl" :headers="headers" :on-success="handleSuccess" :on-error="handleError" :on-progress="handleProgress" :file-list="fileList" :limit="limit" :multiple="multiple" :data="formData" :auto-upload="autoUpload" :show-file-list="showFileList" > <el-button size="small" type="primary">点击上传</el-button> </el-upload> </template> ``` 其中,我们需要设置 `action` 属性为文件上传的接口地址,同时需要设置 `on-success`、`on-error` 和 `on-progress` 等事件来处理上传成功、上传失败和上传进度。 接下来,我们可以在组件的 `mounted` 钩子函数中初始化 axios 并设置分片大小: ```js import axios from 'axios'; export default { name: 'UploadDemo', data() { return { fileList: [], uploadUrl: 'http://example.com/upload', limit: 3, multiple: true, formData: {}, autoUpload: true, showFileList: true, headers: {}, chunkSize: 5 * 1024 * 1024 // 5MB }; }, mounted() { axios.defaults.headers.post['Content-Type'] = 'multipart/form-data'; axios.defaults.timeout = 60000; // 超时时间 axios.defaults.retry = 3; // 重试次数 axios.defaults.retryDelay = 1000; // 重试间隔 // 设置分片大小 axios.defaults.maxContentLength = this.chunkSize; axios.defaults.maxBodyLength = this.chunkSize; }, methods: { // 上传文件 handleUpload(file) { const formData = new FormData(); formData.append('file', file); return axios.post(this.uploadUrl, formData, { headers: this.headers, onUploadProgress: progressEvent => { const percentCompleted = Math.round( (progressEvent.loaded * 100) / progressEvent.total ); console.log(percentCompleted); } }); }, // 上传成功回调 handleSuccess(response, file, fileList) { console.log('上传成功:', response); }, // 上传失败回调 handleError(error, file, fileList) { console.log('上传失败:', error); }, // 上传进度回调 handleProgress(event, file, fileList) { console.log('上传进度:', event.percent); } } }; ``` 在 `handleUpload` 方法中,我们使用 axios 的 `post` 方法来上传文件,并设置了 `onUploadProgress` 方法来监听上传进度。在 `mounted` 钩子函数中,我们设置了 axios 的默认参数,包括超时时间、重试次数、重试间隔和分片大小等。 需要注意的是,由于 el-upload 组件不支持分片上传,因此我们需要手动控制上传的文件数量,以避免同时上传过多的文件导致服务器崩溃。我们可以通过设置 `limit` 属性来控制上传的文件数量,例如设置为 3 表示一次最多只能上传 3 个文件。 另外,如果需要支持断点续传,我们需要在上传文件时记录已上传的文件块数量和位置,并在下次上传时从上次的位置继续上传。这部分内容比较复杂,需要根据具体的需求来实现,这里不再赘述。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值