扩展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); } },