上传咱们通常都是用“input[type=file]”控件。当你用此控件时,你就受权了网页和服务器访问对应的文件,就能够获得File对象。javascript
友情提示在,在Android手机webview中,是不支持上传文件的,网上说是修改Android端的代码,但我没试过,咱们这边是使用客户端提供的接口来实现上传的。html
下面的示例代码能够在这里查看到。html5
该属性代表了服务器端可接受的文件类型,能够限制你手机选择相关的文件,若是限制多个,能够用逗号分割,下面的代码就表示只能选择图片与音频相关的文件:java
<input accept="image/*,audio/*" type="file"/>
在移动端,点击后会让你选择拍照或相册,仍是蛮高大上的。下图是UC浏览器中:node
通常选择文件都会使用“change”事件,下面的代码就是绑定了change事件,弹出文件大小:web
var upload = document.getElementById('upload'); upload.addEventListener('change', function() { var file = upload.files[0]; alert(file.size); }, false);
1) 有些手机浏览器在点击的时候,会弹出键盘选择,我用onfocus="this.blur()",来强制失去焦点。canvas
<input type="file" id="upload" onfocus="this.blur()"/>
2) 当选择过一次后,再次选择同一个文件,“change”事件不会触发,由于value没有改变,在网上看到个方法,我尚未在实际项目中使用,兼容性有待考证。api
使用“Node.cloneNode”复制上传元素,再用“Node.replaceChild”替换节点。数组
这里注意下:克隆一个元素节点会拷贝它全部的属性以及属性值,但不会拷贝那些使用addEventListener()方法或者node.onclick = fn用JavaScript动态绑定的事件。浏览器
upload.addEventListener('change', function() { var upload = document.getElementById('upload'); //每次要动态获取 var file = upload.files[0]; console.log(file.size); //解决上传相同文件不触发onchange事件 var clone = upload.cloneNode(true); clone.onchange = arguments.callee; //克隆不会复制动态绑定事件 clone.value = ''; upload.parentNode.replaceChild(clone, upload); }, false);
用户所选择的文件都存储在了一个FileList对象上,其中每一个文件都对应了一个File对象
File对象负责处理那些以文件形式存在的二进制数据,也就是操做本地文件。
File对象是Blob【下面会提到】的特殊类型,即大块的二进制数据,File对象的尺寸及类型等属性都继承自Blob。
1)File对象能够经过3种方式获取:
1. <input>元素上选择文件后返回的FileList对象中的成员
2. 拖放操做【Drag或Drop】生成的 DataTransfer对象内files属性中的成员
3. HTMLCanvasElement上执行mozGetAsFile()方法后的返回结果
document.getElementById('upload').files[0]//选取第一个文件对象
2)File对象有9个属性,这里就只介绍3个:
1. name:当前File对象所引用文件的文件名,不包括路径,只读。
2. size:文件大小,单位为字节,只读的64位整数.
3. type:MIME类型,只读字符串,若是类型未知,则返回null。有些移动端的浏览器明明选择了图片,返回的倒是null,很是坑。
还有3个非标准的方法:getAsBinary()、getAsDataURL()和getAsText(in DOMString encoding)。
这3个方法如今已通过时,如今用FileReader对象中的方法来取代。
web应用程序能够异步的读取存储在用户计算机上的文件(或者原始数据缓冲)内容,可使用File对象或者Blob对象来指定所要处理的文件或数据。
1) readAsArrayBuffer():在返回的result属性中将包含一个ArrayBuffer对象【缓冲数组,是一种用于呈现通用、固定长度的二进制数据的类型】以表示所读取文件的内容
Blob能够“append”,ArrayBuffer数据。ArrayBuffer存在的意义就是做为数据源提早写入在内存中,就是提早钉死在某个区域,长度也固定。
2) readAsBinaryString():result属性中将包含所读取文件的原始二进制数据
3) readAsDataURL():result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容
4) readAsText():result属性中将包含一个字符串以表示所读取的文件内容
下面的代码是获取data:URL,能够将返回的result内容赋值给img的src,用于预览等操做。
var reader = new FileReader(); reader.readAsDataURL(file); reader.onload = function(e) { var img = new Image(); img.src = this.result; console.log(this.result); };
console.log(this.result)内容以下:
URL对象是硬盘上指向文件的URL。上面的例子中获取图片的引用,经过读取data URI,data URI是个一大串的字符。
图片本来就在硬盘上,还要转换成另外一个格式再用,有点绕了,彻底能够直接引用文件的URL,下面是两个方法:
1) URL.createObjectURL():接收一个文件的引用(File或Blob对象)返回一个URL对象
2) URL.revokeObjectURL():销毁建立的URL
var url = URL.createObjectURL(file); var img = new Image(); img.src = url; img.onload = function(e) { window.URL.revokeObjectURL(this.src); //销毁 } console.log(url);
console.log(url)内容以下:
在移动端须要作个兼容性判断:
window.URL = window.URL || window.webkitURL;
Blob(binary large object)对象表明了一段二进制数据,就是一个包含只读原始数据的类文件对象。
File接口基于Blob,继承了Blob的功能,而且扩展支持了用户计算机上的本地文件。
1)建立Blob对象的4种方法:
1. 调用Blob构造函数
2. 使用一个已有Blob对象上的slice()方法切出另外一个Blob对象
3. 调用canvas对象上的toBlob方法
4. 过气的方法,经过BlobBuilder接口建立,但兼容性很差,而且现有的BlobBuilder实现都是带前缀的
2)利用Blob对象,生成可下载文件
var blob = new Blob(["pwstrick"]);//数组中添加DOMString对象 var a = document.createElement("a"); a.href = URL.createObjectURL(blob);//建立URL对象 a.download = "test.txt";//HTML5新属性 a.textContent = "test"; document.getElementsByTagName('body')[0].appendChild(a);
生成一个“a”标签,而且点击这个连接,能够下载一个txt文本,内容是“pwstrick”。
3)经过slice方法,将二进制数据按照字节分块,返回一个新的Blob对象
upload.addEventListener('change', function() { var upload = document.getElementById('upload'); //每次要动态获取 var file = upload.files[0]; var start = 0; var chunk = 1024 * 10; //10KB var end = start + chunk; var size = file.size; while (start < size) { segment(file, start, end); start = end; end = start + chunk; if (end > size) { end = size; } } }, false); function segment(file, start, end) { var reader = new FileReader(); reader.onload = function(evt) { console.log(['Read bytes: ', start, ' - ', end].join('')); }; var blob = file.slice(start, end); reader.readAsBinaryString(blob); }
XMLHttpRequest Level 2添加了一个新的接口FormData。
利用FormData对象,可使用键值对来模拟一个完整的表单,而后使用XMLHttpRequest发送这个"表单"。
使用FormData的最大优势就是咱们能够异步上传一个二进制文件。
var formData = new FormData(); formData.append("name", "value");//普通键值对 formData.append("blob", blob); //传递一个blob对象 formData.append("file", file); //传递一个file对象 var oReq = new XMLHttpRequest(); oReq.open("POST", "http://xx.com"); oReq.send(formData);
参考资料:
https://developer.mozilla.org/zh-CN/docs/Using_files_from_web_applications 在web应用中使用文件
http://javascript.ruanyifeng.com/htmlapi/file.html 文件和二进制数据的操做
http://www.iunbug.com/archives/2012/06/04/208.html [译]JavaScript文件操做基础
http://www.iunbug.com/archives/2012/06/05/254.html [译]JavaScript文件操做URL对象
http://www.html5rocks.com/zh/tutorials/file/dndfiles/ 经过 File API 使用 JavaScript 读取文件