、良生- input type=file与文件上传
本文所说的input type=file指的是type类型是file的input元素,最简HTML代码如下:
<input type=file>
但是,为了习惯,我们多写成:
<input type="file">
在HTML5出现之前(XHTML),我们的闭合规则则有些出入:
<input type="file" />
顾名思义,选择文件,并上传文件。
在万恶的旧时代,HTML5还没有出现之前,原生的file input表单元素只能让我们一次上传一张图片。无法满足一次上传多图的交互需求,所以,很多场景,就被swfupload.js给取代了,有点逐渐淡出人们视野的感觉。
然,技术发展,日新月异,三十年河东,三十年河西。随着原生HTML5表单对多图(multiple属性)、上传前预览,二进制上传等支持越来越广泛,原生的file input表单元素又迎来了新的升级,flash为背景的swfupload.js注定要落寞。
但是,对于PC项目,IE8-IE9浏览器还是不能忽略的。所以,现在,很流行的一种处理方式,就是HTML5 file上传和flash swfupload上传一起整合的模式,优先使用原生HTML5上传,不支持的,使用flash上传。我之前有篇关于HTML5上传的文章,每天访问量很高的:“基于HTML5的可预览多图片Ajax上传”,大家有兴趣可以看看。
如果想使用浏览器原生特性实现文件上传(如图片)效果,父级的form元素有个东西不能丢,就是:
enctype="multipart/form-data"
enctype属性规定在发送到服务器之前应该如何对表单数据进行编码,默认的编码是:”application/x-www-form-urlencoded“。对于普通数据是挺适用的,但是,对于文件,科科,就不能乱编码了,该什么就是什么,只能使用multipart/form-data作为enctype属性值。
无论是旧时代的单图上传,还是HTML5中的多图上传,均是如此。
文件,尤其图片,上场前能够预览,是很棒的交互体验。不走服务器,不耗费流量,多棒!
理想虽好,实现起来……
在HTML5还没出现的旧时代,只有低版本的IE浏览器貌似有方法,使用私有的滤镜,超越安全的限制(其实是利用了不好的东西),实现图片直接预览;但是呢,那个时候,Chrome, FireFox没有这一出,于是,想要使用原生file input实现图片的上传前预览,兼容性坎很难跨过去。
但是,后来,HTML5来了,我们出现了转机,IE10+以及其他现代浏览器,可以让我们直接读取图片的数据,然后在页面上呈现,实现了上传前预览;加上之前老IE的滤镜策略,貌似,可行。但是呢但是,老的IE浏览器只能最多一次选择一个文件,因此,只有单图上传的时候,大家可以考虑考虑。
传统的form提交,是要改变页面流的,也就是刷新后跳转。好的体验应该是走Ajax交互的。HTML5里面支持二进制formData数据提交,因此,可以从容Ajax提交上传的文件数据;那老旧的IE浏览器怎么办?
一般方法如下:
<form action="" method="post" enctype="multipart/form-data" target="uploadIframe">< <iframe id="uploadIframe"></iframe>
var doc = iframe.contentDocument ? iframe.contentDocument : frames[iframe.id].document; var response = doc.body && doc.body.innerHTML;
OK, 当然,你也可以不用像上面这么麻烦,直接使用jquery.form.js. 原理呢,就是上面这样,但是,不需要这么麻烦。
原生的file input不收待见的另外一个原因是:长的丑还不好控制。
举个例子,下图这个“选择文件”这几个文字,我们就不好对file控件动刀子实现自定义:
file input框
怎么办呢?
有一种方法是这样的: 让file类型的元素透明度0,覆盖在我们好看的按钮上。然后我们去点击好看的按钮,实际上点击是是file元素。
然而,此方法有一些不足:
更好的方法是,使用label元素与file控件关联,好处在于:
<label class="ui_button ui_button_primary" for="xFile">上传文件</label> <form><input type="file" id="xFile" style="position:absolute;clip:rect(0 0 0 0);"></form>
效果如下(真实实时效果):
input file类型控件有一个属性,名为
accept
, 可能有些小伙伴不太了解。可以用来指定浏览器接受的文件类型,也就是的那个我们打开系统的选择文件弹框的时候,默认界面中呈现的文件类型。例如:
accept="image/jpeg"
,则界面中只有jpg图片,如下截图,同时,窗体右下方是“自定义文件”按钮:
自定义文件
实际开发的时候,很少只允许传jpg图片,应该都是只能传图片类型,此时,可以使用:
accept="image/*"
于是乎,“自定义文件”按钮变成了语义更明确的“图片文件”:
图片文件
accept属性值其实是MIME类型, 例如下面几个可能常用的:
accept="application/pdf" accept="audio/x-mpeg" accept="text/html" .accept="video/x-mpeg2"
然后,多个属性值使用逗号分隔,例如:
<input accept="audio/*,video/*,image/*">
现代浏览器直接value = "", 有些IE浏览器貌似不行,好像使用file.outerHTML = file.outerHTML,我自己没测试。
不过我觉得比较麻烦,还要判断浏览器什么的。像本文的Ajax单图上传,直接form.reset()就可以了。
以上~
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
typeof 运算符是 JavaScript 的基础知识点,尽管它存在一定的局限性(见下文),但在前端js的实际编码过程中,仍然是使用比较多的类型判断方式。
因此,掌握该运算符的特点,对于写出好的代码,就会起到很大的帮助作用。
typeof 返回一个字符串,表示该操作值的数据类型,基本语法:
typeof operand
typeof(operand)
可能返回的类型字符串有:string, boolean, number, bigint, symbol, undefined, function, object。
将根据可能的返回类型,进行以下的分类介绍,对typeof的使用方法一网打尽。
string 和 boolean
字符串、布尔值分别返回 string、boolean。包括 String() 和 Boolean()。
typeof '1' // 'string'
typeof String(1) // 'string'
typeof true // 'boolean'
typeof Boolean() // 'boolean'
数字返回 number,包括 Number()、NaN 和 Infinity 等,以及 Math 对象下的各个数学常量值。
BigInt 数字类型值返回 bigint,包括 BigInt(1)。
typeof 1 // 'number'
typeof NaN // 'number'
typeof Math.PI // 'number'
typeof 42n // 'bigint'
typeof BigInt(1) // 'bigint'
symbol 值返回 symbol,包括 Symbol()。
typeof Symbol() // 'symbol'
typeof Symbol('foo') // 'symbol'
typeof Symbol.iterator // 'symbol'
undefined 本身返回 undefined。
不存在的,或者定义了但未赋初值的变量,都会返回 undefined。
还有 document.all 等浏览器的非标准特性。
typeof undefined // 'undefined'
typeof ttttttt // 'undefined'
typeof document.all // 'undefined'
函数返回 function。
包括使用es6的 class 类声明的。
还有各个内置对象 String、Number、BigInt、Boolean、RegExp、Error、Object、Date、Array、Function、Symbol 本身。
以及 Function(),new Function()。
function func () {}
typeof func // 'function'
typeof class cs {} // 'function'
typeof String // 'function'
typeof RegExp // 'function'
typeof new Function() // 'function'
对象、数组、null、正则表达式,都返回 object。
包括 Math、jsON 对象本身。
还有使用 new 操作符的数据,除了 Function 以外。
typeof {} // 'object'
typeof [] // 'object'
typeof null // 'object'
typeof /d/ // 'object'
typeof Math // 'object'
typeof new Number(1) // 'object'
关于其他大部分的 JavaScript关键字,得到的结果值都是 object 或 function。
注:多数小写字母开头的是对象 object,多数大写字母开头的都是方法 function。常见的明确知道的方法不算,如 alert,prompt 等方法。
除此以外,还有各js环境下具体实现的宿主对象。
引用错误
在 let 和 const 块级作用域变量定义之前,使用 typeof 会抛错 ReferenceError。因为块级作用域变量,会在头部形成 暂存死区,直到被初始化,否则会报引用错误。
typeof t
let t = 1
// VM327:1 Uncaught ReferenceError: t is not defined
// at <anonymous>:1:1
如果是使用 var 定义变量,不会报错,返回 undefined 。
有变量提升,不会形成暂时死区。
对于 typeof null === 'object' ,记住即可,可能的解释:
在JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于null代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0,typeof null 也因此返回 "object"。
typeof 的局限性
typeof 的局限性,在于无法精确判断出 null、数组、对象、正则 的类型。所以如果要精准判断,还需要使用其他技术手段,或组合判断。如下,判断数组类型:
Object.prototype.toString.call([]) // '[object Array]'
[] instanceof Array // true
[].constructor === Array // true
其中,Object.prototype.toString.call 是javascript中用于准确判断数据类型的通用手段。
BigInt 来自于 ES11 增加的一种最新的基础类型,可以用任意精度表示整数。
它提供了一种表示大于 2^53 - 1 整数的方法,能表示任意大的整数。
它是通过在整数末尾附加 n 或调用构造函数 BigInt() 来创建的。IE 不支持。
10n
BigInt(99) // 99n
注意点:
-
ocumentType类型在Web浏览器中并不常用,仅有Firefox、Safari和Opera支持它1。DocumentType包含着与文档的doctype有关的所有信息,它具有下列特征:
1Chrome 4.0也支持DocumentType类型。
nodeType的值为10;
nodeName的值为doctype的名称;
nodeValue的值为null;
parentNode是Document;
不支持(没有)子节点。
在DOM1级中,DocumentType对象不能动态创建,而只能通过解析文档代码的方式来创建。支持它的浏览器会把DocumentType对象保存在document.doctype中。DOM1级描述了DocumentType对象的3个属性:name、entities和notations。其中,name表示文档类型的名称;entities是由文档类型描述的实体的NamedNodeMap对象;notations是由文档类型描述的符号的NamedNodeMap对象。
通常,浏览器中的文档使用的都是HTML或XHTML文档类型,因而entities和notations都是空列表(列表中的项来自行内文档类型声明)。但不管怎样,只有name属性是有用的。这个属性中保存的是文档类型的名称,也就是出现在<!DOCTYPE之后的文本。以下面严格型HTML 4.01的文档类型声明为例:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
DocumentType的name属性中保存的就是"HTML":
alert(document.doctype.name); //"HTML"
IE及更早版本不支持DocumentType,因此document.doctype的值始终都等于null。可是,这些浏览器会把文档类型声明错误地解释为注释,并且为它创建一个注释节点。IE9会给document.doctype赋正确的对象,但仍然不支持访问DocumentType类型。
想要了解更多Java基础知识,可以点击评论区链接和小编一起学习java吧,此视频教程为初学者而著,零基础入门篇!给同学们带来全新的Java300集课程啦!java零基础小白自学Java必备优质教程_手把手图解学习Java,让学习成为一种享受_哔哩哔哩_bilibili
*请认真填写需求信息,我们会在24小时内与您取得联系。