最近使用了elementUI提供的upload组件上传文件,总结下使用过程中的一些心得。本文不会介绍如何使用elementUI中的upload组件,因为官网本身就已经介绍的很详细了。
本文主要包括以下几个问题:
/packages/upload
文件夹下面;upload组件提供了两种上传文件的方式:
针对上述两种方式,upload组件提供了属性accept
来限制和校验文件格式。这里,我使用了两个词:
校验:从结果层面上校验,也就是在最后一步才能发现选择不了,同时适用于上述两种方式,其中校验又包括两种:
接下来我们结合upload组件源码来分析下实现原理。
限制形式的主要原理就是原生input元素的accept属性(源码/packages/upload/src/upload.vue文件第206行):
<input class="el-upload__input" type="file" ref="input" name={name} on-change={handleChange} multiple={multiple} accept={accept}></input>
当没有添加accept属性的时候,系统的文件选择框中的文件都是可选的:
<input type="file" />
当添加了accept之后,比如.png
,系统的文件选择框中只有符合格式的文件才是可选的:
<input type="file" accept=".png" />
如何支持多种文件格式上传呢?看下原生input元素accept属性的文档,会发现accept是支持逗号分割的多种文件格式的:
<input type="file" accept=".png,.jpg,.jpeg" />
开发的时候发现一个有意思的问题,就是如果accept里面.jpg和.jpeg只写一个,另外一种格式也是可以选择的:
<input type="file" accept=".png,.jpeg" />
// 或者
<input type="file" accept=".png,.jpg" />
所以,jpg和jpeg有啥关系?查找了下资料,发现这两种格式并没有任何区别,至于为什么会有两个名字,说是先有了jpeg,然后Windows的早期版本规定文件的扩展名只能是三个字符,所以就变成了jpg。感兴趣的可以参考这篇文章。
所以,
这个时候就只能依赖下面的校验方式了。
当使用拖拽方式上传文件的时候,是可以拖拽任何文件的,所以只能在拖拽完成的时候去校验文件格式。那么,应该去校验哪些格式呢?从upload组件使用者的角度来说,无论是input元素方式还是拖拽方式,都应该是保持统一的。也就是,原生input的accept属性支持的格式,在使用拖拽方式的时候,也都得支持。
所以,先看下input的accept属性支持的格式类型:
.
开头;upload组件源码针对上述三种类型做的相应处理(/packages/upload/src/upload-dragger.vue
文件onDrop方法)如下:
this.$emit('file', [].slice.call(e.dataTransfer.files).filter(file => {
const { type, name } = file;
const extension = name.indexOf('.') > -1
? `.${ name.split('.').pop() }`
: '';
const baseType = type.replace(/\/.*$/, '');
return accept.split(',')
.map(type => type.trim())
.filter(type => type)
.some(acceptedType => {
if (/\..+$/.test(acceptedType)) { // 1. 扩展名形式
return extension === acceptedType;
}
if (/\/\*$/.test(acceptedType)) { // 3. "audio/*" "video/*" "image/*"
return baseType === acceptedType.replace(/\/\*$/, '');
}
if (/^[^\/]+\/[^\/]+$/.test(acceptedType)) { // 2. MIME类型
return type === acceptedType;
}
return false;
});
}));
upload组件提供了自定义校验的钩子函数:before-upload。根据该函数的返回值决定是继续还是终止(/packages/upload/src/upload.vue
文件第91行):
const before = this.beforeUpload(rawFile);
结论:不能
dragEvent有一个dataTransfer属性,这个属性有一个setDragImage方法,该方法看似可以用来自定义拖拽样式。但是,这个方法有一个使用限制:只能在dragstart事件中调用。
但是当从操作系统拖拽文件到浏览器中的时候,dragstart事件是不会触发的,所以setDragImage方法不能实现我们的目的。
upload组件dom中包含一个不显示的input元素,当点击组件的时候触发input元素的click事件(/packages/upload/src/upload.vue):
handleClick() {
if (!this.disabled) {
this.$refs.input.value = null;
this.$refs.input.click();
}
}
如有错误,欢迎留言讨论。
idea官方推送了2020.2.4版本的更新,那么大家最关心的问题来了,之前激活idea202...
在Flash Player 10.1及以上版本中,adobe新增了全局错误处理程序UncaughtErrorEv...
本文转载自微信公众号「SH的全栈笔记」,作者SH。转载本文请联系SH的全栈笔记公...
本文转载自微信公众号「SQL数据库」,作者丶平凡世界 。转载本文请联系开发公众...
CKeditor,以前叫FCKeditor,已经使用过好多年了,功能自然没的说。最近升级到3....
来源:DeepenStudy 漏洞文件:js.asp % Dimoblog setoblog=newclass_sys oblog.a...
问题:我们在做flex的开发中,如果用到别人搭建好的框架,而别人的server名称往...
大家好,我是狂聊君。 今天来聊一聊 Mysql 缓存池原理。 提纲附上,话不多说,直...
本文实例讲述了AJAX+Servlet实现的数据处理显示功能。分享给大家供大家参考,具...
前言 项目开发中不管是前台还是后台都会遇到烦人的null,数据库表中字段允许空值...