这篇文章发布于 2015年11月24日,星期二,00:01,归类于 HTML相关。 阅读 262793 次, 今日 9 次 56 条评论
by zhangxinxu from http://www.zhangxinxu.com
本文地址:http://www.zhangxinxu.com/wordpress/?p=5071
一、良生- 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上传”,大家有兴趣可以看看。
二、莲安-原生input上传与表单form元素
如果想使用浏览器原生特性实现文件上传(如图片)效果,父级的form
元素有个东西不能丢,就是:
enctype="multipart/form-data"
enctype
属性规定在发送到服务器之前应该如何对表单数据进行编码,默认的编码是:”application/x-www-form-urlencoded
“。对于普通数据是挺适用的,但是,对于文件,科科,就不能乱编码了,该什么就是什么,只能使用multipart/form-data
作为enctype
属性值。
无论是旧时代的单图上传,还是HTML5中的多图上传,均是如此。
三、沿见-原生file input图片上传前预览与Ajax上传
文件,尤其图片,上场前能够预览,是很棒的交互体验。不走服务器,不耗费流量,多棒!
理想虽好,实现起来……
在HTML5还没出现的旧时代,只有低版本的IE浏览器貌似有方法,使用私有的滤镜,超越安全的限制(其实是利用了不好的东西),实现图片直接预览;但是呢,那个时候,Chrome, FireFox没有这一出,于是,想要使用原生file input实现图片的上传前预览,兼容性坎很难跨过去。
但是,后来,HTML5来了,我们出现了转机,IE10+以及其他现代浏览器,可以让我们直接读取图片的数据,然后在页面上呈现,实现了上传前预览;加上之前老IE的滤镜策略,貌似,可行。但是呢但是,老的IE浏览器只能最多一次选择一个文件,因此,只有单图上传的时候,大家可以考虑考虑。
传统的form提交,是要改变页面流的,也就是刷新后跳转。好的体验应该是走Ajax交互的。HTML5里面支持二进制formData数据提交,因此,可以从容Ajax提交上传的文件数据;那老旧的IE浏览器怎么办?
一般方法如下:
- form元素新增
target
属性,其值指向页面内隐藏的一个<iframe>
元素的id
, 如下示意:<form action="" method="post" enctype="multipart/form-data" target="uploadIframe">< <iframe id="uploadIframe"></iframe>
- 处理
<iframe>
元素的onload
事件,获得返回内容(如下代码示意),具体细节非本文重点,不表。var doc = iframe.contentDocument ? iframe.contentDocument : frames[iframe.id].document; var response = doc.body && doc.body.innerHTML;
OK, 当然,你也可以不用像上面这么麻烦,直接使用jquery.form.js. 原理呢,就是上面这样,但是,不需要这么麻烦。
四、恩和-原生file input大小、按钮文字等UI自定义
原生的file input不收待见的另外一个原因是:长的丑还不好控制。
举个例子,下图这个“选择文件”这几个文字,我们就不好对file控件动刀子实现自定义:
怎么办呢?
有一种方法是这样的:
让file类型的元素透明度0
,覆盖在我们好看的按钮上。然后我们去点击好看的按钮,实际上点击是是file
元素。
然而,此方法有一些不足:
- 尺寸控制不灵活。CSS
width
属性有些浏览器不管用,需要使用size
,然后高度控制也不精准,我们很难正好覆盖在好看的自定义按钮上。 - 样式不好控制,按钮的
hover
态以及active
态不好处理。 - HTML结构限制以及定位成本。
更好的方法是,使用label
元素与file
控件关联,好处在于:
- 点击自定义的漂亮按钮就是点击我们file控件;
- 没有尺寸控制不精确的问题;
- 没有不能响应hover态active态的问题;
- 我们的漂亮按钮甚至可以在form表单元素的外面,例如:
<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>
效果如下(真实实时效果):
五、盈年-file类型控件的accept属性
input file类型控件有一个属性,名为accept
, 可能有些小伙伴不太了解。可以用来指定浏览器接受的文件类型,也就是的那个我们打开系统的选择文件弹框的时候,默认界面中呈现的文件类型。例如:accept="image/jpeg"
,则界面中只有jpg图片,如下截图,同时,窗体右下方是“自定义文件”按钮:
实际开发的时候,很少只允许传jpg图片,应该都是只能传图片类型,此时,可以使用:
accept="image/*"
于是乎,“自定义文件”按钮变成了语义更明确的“图片文件”:
但是,需要注意的是,虽然使用accept="image/*"
很方便,但是在Chrome浏览器下,可能会有文件选择窗口打开非常慢点问题,因此,如果仅仅是上传图片,建议使用:
accept="image/png, image/jpeg, image/gif, image/jpg"
accept
属性值其实是MIME类型, 例如下面几个可能常用的:
accept="application/pdf" accept="audio/x-mpeg" accept="text/html" .accept="video/x-mpeg2"
然后,多个属性值使用逗号分隔,例如:
<input accept="audio/*,video/*,image/*">
补充于2020-08-11
accept属性在部分Android设备下可能是无效的。
继续补充。
关于capture属性
input file文件选择框还支持capture
属性,允许开发者调用一些设备的媒体功能。
调用前置摄像头:
<input type="file" name="image" accept="image/*" capture="user">
调用后置摄像头:
<input type="file" name="image" accept="image/*" capture="environment">
调用麦克风和摄像头:
<input type="file" name="image" accept="audio/*" capture=>
六、内河-input file只选择文件夹而不是文件
试试下面的代码,测试了下,Chrome浏览器下是可以的,Firefox浏览器下也是可以的,IE貌似还不行。
<input type="file" webkitdirectory directory multiple/>
七、又及-input file值的清除
现代浏览器直接value = ""
, 有些IE浏览器貌似不行,好像使用file.outerHTML = file.outerHTML
,我自己没测试。
不过我觉得比较麻烦,还要判断浏览器什么的。像本文的Ajax单图上传,直接form.reset()
就可以了。
以上~
本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:http://www.zhangxinxu.com/wordpress/?p=5071
(本篇完)
- Ajax Upload多文件上传插件翻译及中文演示 (0.656)
- HTML5 file API加canvas实现图片前端JS压缩并上传 (0.498)
- XMLHttpRequest实现HTTP协议下文件上传断点续传 (0.483)
- 直接剪切板粘贴上传图片的前端JS实现 (0.386)
- 基于HTML5的可预览多图片Ajax上传 (0.285)
- 密码强度效果最佳实现一定是HTML meter元素 (0.241)
- CSS :focus伪类JS focus事件提高网站键盘可访问性 (0.213)
- 不使用file类型input也能触发文件上传 (0.212)
- CSS ::file-selector-button伪元素简介 (0.212)
- HTML5 progress元素的样式控制、兼容与实例 (0.208)
- 基于HTML5 drag/drop模块拖动插入排序删除完整实例 (RANDOM - 0.015)
好奇这个 文件选择了之后 是存放到哪里了? 内存中吗?
可以啊,adblock专用
自定义拦截广告代码: zhangxinxu.com##body > *:not(div):not(script):not(main)
adblock用户专享
博主,请问你对移动端有什么研究吗,我最近做移动端上传遇到安卓一些机型,无法上传pdf或者是某些浏览器不行,有些又可以在es文件管理器进行选择pdf。目前web前端有什么手段可以处理这些兼容性吗
大佬,我现在做文件上传遇到一个问题,当使用多文件上传,选择多个比较大的文件时,在windos环境中,浏览器会假死,过很久才会触发input 或者onchage事件,atnd 或者element都存在此问题,而百度网盘完全没问题,且如果我是选择拖拽上传就不会卡死,只是点击呼出文件选择框后点击确认后,就进入浏览器假死,等很久后才有 input 或者onchage的打印,目前亲测 头条 阿里等都不行,就百度网盘完美兼容。
accept: ‘image/png,image/jpeg,video/mp4’,
支持选择多个文件的input, 删除单个文件时怎么做比较好
accept=“.svg”
请问 svg怎么用input实现上传,accept不支持svg吗。。
mime type设置为image/svg+xml
用了还是没办法实现input上传图片的时候上传svg图片,chrome不可以,ff是可以的,不知道该怎么解决这个问题,求大神指导
Hello~大大 请问下HTML打开的文件选择模态对话框能更改默认位置吗?
希望能够默认打开在屏幕正中间。
这个需求很奇怪。
小哥哥,您好,请问你这个问题解决了嘛,可不可以向你取取经
请问file控件的默认地址可控吗,我想点开之后到指定的目录下
类型为file的input中,如何使用属性accept筛选后缀名为.dat的文件
已解决,accept = “.dat”
张大大,有个问题非常头痛,html 的file文件域 点击文件域默认会有一个文件选择框, 手机 不同的浏览器是不同显示选择文件的界面(这个问题先忽略)
比较困扰我的一个问题, 弹出文件框后,如果我不选择文件, 下次这个文件框就弹不出来, 也就没法进行文件上传的操作了, 这种情况出现在钉钉, UC浏览器里面,
微信,QQ,其他的好几个浏览器(QQ浏览器,百度APP,自带浏览器) 都是正常的。
我测试这个问题 body标签 就只有下面内容
我用你当前页面的连接测试 和我上面的测试结果一样。
由于我们是基于钉钉做的应用, 这个问题必须在钉钉里面解决, 麻烦张大大能看看这个问题? 期望您能回复 ♪(・ω・)ノ !
钉钉我没用过诶,这个可以找钉钉的产品,UC浏览器可以找裕波反馈。
input选取HTML文件上传提交的对象是什么啊
现在用到formdata上传多个Input=file的数据到后台,但是每次只能传一个值过去,不知道是为什么,下面是我的代码,麻烦大神帮忙看一下怎样解决这种问题,谢谢:
function getForm01Data() {
var fd = new FormData();
// 文件
var file_data = $(‘input[type=”file”]’)[0].files;
for (var i = 0; i < file_data.length; i++) {
fd.append('file_' + i, file_data[i]);
}
// 其它数据
var other_data = $('#Form01').serializeArray();
$.each(other_data, function (key, input) {
fd.append(input.name, input.value);
});
return fd;
}
您好,讲得挺清楚的,多问一点,请问做多图上传的时候,想要删除某一张再上传,这样的实现思路是怎么样的?谢谢,如果能发邮件告知就十分感谢了。
请问用label的方法,选择文件后我想显示文件名怎么做?
删除没法用!~
少年,那是你用错了
file 存在多个文件的时候 支持删除一个文件? 并不是删除全部文件啊!
accept=”image/*”,在Chrome浏览器下,可能会有文件选择窗口打开非常慢,哇偶,好流弊。
大神你遇到过input file在app中无法访问的问题吗
app做一下设定就好了
(前端)通过文件扩展名控制文件上传格式靠谱吗?(因为 angular-file-upload FileItem时, excel,exe他两的MIME都是application/x-msdownload,DOM的type属性也会有类似问题,所以没法区别控制)
accept=”image/*”,在chrome等一些浏览器上点击file控件,到出现文件选择框延迟很严重。改成accept=”image/gif,image/jpeg,image/png”才能解决这个问题,百度的webUploader的代码里面就有这个问题
已成经典,帮了我很多!
您好,在转发您的帖子的时候发现第三节的方法1中的示例代码第一行可能有误,多了一个左尖括号。猜测应该是 form 标签的闭合标签。
为什么lable和input都跟你一样,上传文件按钮没用
结合label的方式确实很方便,但是有可能存在兼容问题(忽略IE),如我用firefox20下试点了就没反应了(影响到功能),所以目前通常做法还是把input设为透明,虽然可能体验会略差,但至少还能点!
求助: input type=file的表单元素,设置multiple=”true”能在chrome和FF上进行文件多选,然而监听其onchange事件得到的value值却只有选中的第一个文件的。我需要获取每一个被选中的文件的路径,怎么办?
chrome浏览器中使用accept为image/*时,导致文件打开特别慢,起码得等待3秒以上,可能是chrome的bug?
chrome版本为52以上
我也发现了这个问题,真心好慢
请问你是怎么解决的?求教。
把图片格式限制写死就好了accept = ”image/png,image/gif,image/jpeg,image/jpg“
不要用* 把需要过滤的直接写出来
不仅仅是image/*的问题,你可以试着设置成image/svg,依旧是非常的慢。可能是chrome处理SVG文件的问题
我想问下html5 file 放在微信里,只能上传一张图片,怎么才能上传多张图片
我也想问这个问题,最近在做这个微信公众号里一次上传多张图片的需求;html5的multiple属性 pc端是可以的,移动端目前好像只有QQ浏览器支持,微信里不支持。请问你这个问题解决了吗?
旭哥,真心服!label来替代input透明的方法
话说是不是 html5 file 放在 webview 里,是不能点击的哦…这个怎么解决呢
input file在webview中是可以点击的
博主,你好,
“form元素新增target属性,其值指向页面内隐藏的一个元素的id, 如下示意:”
我试了一下,这里应该是iframe元素的name啊,不是id。
“HTML5 file上传和flash swfupload上传一起整合的模式,优先使用原生HTML5上传,不支持的,使用flash上传”,很想知道如何实现,具体的就是,如果支持HTML5肯定好办,就是不支持的时候切换到flash上传,对于这个flash上传的东东,有专门单独的文件吗?比如博主之前有个兼容复制文本的.swf文件,如果还是使用plupload之类,就感觉没什么意思了,使用swfupload吗?
一直在您的blog中学习了很多知识 哈哈 前一阵子自己也写了关于input[type=file]控件的一些使用技巧
http://fedvic.com/tags/input-type-file/
不错,学习了
你也看安妮宝贝啊
同问,移动端上有没有通用的方案?
现在非常头疼的问题是手机上的文件上传,很多android的操作系统和某些特别的浏览器内核一组合,几乎找不到一个特别靠谱的通用方案,不知道有没有什么心得?
请教一个困扰了很久的问题:h5用FormData对象上传图片。经过插件裁剪后可以得到blob对象,然后我利用这个对象new File,再把这个file加进h5的FormData对象里传给后台,这样可以对图片进行灵活处理(裁剪,压缩等)。但是我在PC,安卓上都可以实现,唯独ios实现不了,也没报错,只是后台接收图片的字段为null,或许你知道是什么原因吗?
这个应该不至于,看看哪里细节有些问题。