我们能够如此简单的实现Ajax
的文件上传要得益于两个新的对象:File
和FormData
对象,还有就是w3c标准化XMLHttpRequest
之后的扩展。现在新的浏览器都支持这些东西。
先来看一下File
对象。
取得File
对象有两个途径:
1、用户在一个<input>
元素上选择文件后返回的FileList
对象。
2、来自由拖放操作生成的 DataTransfer
对象。
这里主要讲的是第一个,第二个有兴趣的同学可以自行查找相关资料。
假如有这样一个inpu
元素:
<input id="file" type="file" name="file">
可以像下面那样获取到File
对象:
var input = document.getElementById("file"); console.log(input.files[0]);
input.files
是就是上面所说的FileList
对象,这是一个数组对象,每一个元素都是一个File
对象。
File
对象的主要属性如下:
name
:当前File
对象所引用文件的文件名。
size
:文件大小,单位是字节。
type
:文件MIME类型。
还有其他一些信息,可以通过浏览器的调试命令行查看。
接下来就是FormData
对象了。
通过这个对象可以模拟一个完整的表单。
获取FormData
对象:
var form = new FormData();
这对象就是一个表单,它可以被XMLHttpRequest
直接发送。
它有一个方法append
,作用就是给FormData
对象添加字段。
比如:
form.append("user", "hehe");
相当于表单里面的一个name
为user,value
为hehe的input
元素。
它的值还可以是一个File
对象:
form.append("file", input.files[0]);
相当于type
为file
的input
元素。
上面那样是从零开始构造,也可以从一个现存的表单来构造FormData
对象。
比如有一个form
元素ID为myForm
:
var myForm= document.getElementById("myForm"); var form = new FormData(myForm);
这样form
元素的表单字段就全部到FormData
对象了。
最后就是被w3c标准化后的XMLHttpRequest
功能更强了。
不仅可以直接发送FormData
对象,还可以监视上传和下载的进度。
如果是图片,需要在上传之前预览的话,那就要用FileReader
对象了。
使用FileReader
对象,web应用程序可以异步的读取存储在用户计算机上的文件(或者原始数据缓冲)内容,可以使用File
对象或者Blob
对象来指定所要处理的文件或数据。
创建一个FileReader
对象:
var reader = new FileReader();
要实现预览图片的话,主要是用它的readAsDataURL
方法,这个方法读取到的文件内容是data:URL
格式的字符串,可以直接放在img
标签的src
里面。
还有一个是它的onload
事件,当读取操作成功完成时触发,可以在读取完成时把结果给img
标签。
来个实例。
HTML代码清单如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>HTML5 File Upload Demo</title> <script type="text/javascript" src="upload.js"></script> <style type="text/css"> * { padding : 0; margin : 0; } .item { border : 2px solid #ccc; padding: 20px; margin: 50px; width: 350px; } </style> </head> <body> <div> <h2>示例</h2> <input id="file" type="file" name="file"> <br> <button type="button" id="button">点击上传</button> <div>进度:<span id="progress"></span></div> <img id="uploadPreview" style="width: 100px; height: 100px;" src="data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%3F%3E%0A%3Csvg%20width%3D%22153%22%20height%3D%22153%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%0A%20%3Cg%3E%0A%20%20%3Ctitle%3ENo%20image%3C/title%3E%0A%20%20%3Crect%20id%3D%22externRect%22%20height%3D%22150%22%20width%3D%22150%22%20y%3D%221.5%22%20x%3D%221.500024%22%20stroke-width%3D%223%22%20stroke%3D%22%23666666%22%20fill%3D%22%23e1e1e1%22/%3E%0A%20%20%3Ctext%20transform%3D%22matrix%286.66667%2C%200%2C%200%2C%206.66667%2C%20-960.5%2C%20-1099.33%29%22%20xml%3Aspace%3D%22preserve%22%20text-anchor%3D%22middle%22%20font-family%3D%22Fantasy%22%20font-size%3D%2214%22%20id%3D%22questionMark%22%20y%3D%22181.249569%22%20x%3D%22155.549819%22%20stroke-width%3D%220%22%20stroke%3D%22%23666666%22%20fill%3D%22%23000000%22%3E%3F%3C/text%3E%0A%20%3C/g%3E%0A%3C/svg%3E" alt="Image preview" /> </div> </body> </html>
首先获取到上传按钮,file input和进度显示的DOM对象:
var btn = document.getElementById("button"); var input = document.getElementById("file"); var pr = document.getElementById("progress");
然后给上传按钮添加点击上传的事件:
btn.addEventListener("click", uploader, false);
接下来实现上传的功能和进度监视的功能。
uploader
上传功能的代码清单:
var uploader = function() { if(input.files.length == 0) { return false; } //创建FormData对象和XMLHttpRequest对象。 var form = new FormData(); var xhr = new XMLHttpRequest(); xhr.upload.addEventListener("progress", updateProgress, false); //监视进度 form.append('file', input.files[0]);//把文件添加到FormData对象 xhr.open("POST", "upload.php"); xhr.send(form);//上传文件 xhr.onreadystatechange = function() { //..... }; };
XMLHttpRequest
分别有四个事件可以监听:
1、progress:处理中。
2、load:传输完成。
3、error:传输失败,出错了。
4、abort:传输退出,被终止了。
如果要监听这四个事件,都必须在调用XMLHttpRequest.open
方法之前设定。
上传和下载都有这个四个事件。
如果是下载,四个事件是由XMLHttpRequest
触发的,也就是要设置在XMLHttpRequest
对象上面:
xhr.addEventListener("progress", updateProgress, false); xhr.addEventListener("load", transferComplete, false); xhr.addEventListener("error", transferFailed, false); xhr.addEventListener("abort", transferCanceled, false);
如果是上传的话,事件是由XMLHttpRequest.upload
触发的,也就是要设置在XMLHttpRequest.upload
属性上面:
xhr.upload.addEventListener("progress", updateProgress, false); xhr.upload.addEventListener("load", transferComplete, false); xhr.upload.addEventListener("error", transferFailed, false); xhr.upload.addEventListener("abort", transferCanceled, false);
这里要注意上面这点区别。
下面是上传进度监听的函数代码清单:
var updateProgress = function(evt) { console.log(evt.lengthComputable); if(evt.lengthComputable) { var prN = Math.round( (evt.loaded / evt.total) * 100 ) + "%"; pr.textContent = prN; } else { pr.textContent = "不能计算进度信息!"; } };
进度信息会在事件属性里面。
upload.js
的完整代码,如下:
document.onreadystatechange = function(){ if(document.readyState == "complete") { var btn = document.getElementById("button"); var input = document.getElementById("file"); var pr = document.getElementById("progress"); //进度处理回调 var updateProgress = function(evt) { console.log(evt.lengthComputable); if(evt.lengthComputable) { var prN = Math.round( (evt.loaded / evt.total) * 100 ) + "%"; pr.textContent = prN; } else { pr.textContent = "不能计算进度信息!"; } }; //上传方法 var uploader = function() { if(input.files.length == 0) { return false; } //创建FormData对象和XMLHttpRequest对象。 var form = new FormData(); var xhr = new XMLHttpRequest(); xhr.upload.addEventListener("progress", updateProgress, false);//监视进度 form.append('file', input.files[0]); //把文件添加到FormData对象 xhr.open("POST", "upload.php"); xhr.send(form); //上传文件 xhr.onreadystatechange = function() { //..... }; }; //图片预览 var preview = function() { var reader = new FileReader(); var filter = /^(?:image\/bmp|image\/cis\-cod|image\/gif|image\/ief|image\/jpeg|image\/jpeg|image\/jpeg|image\/pipeg|image\/png|image\/svg\+xml|image\/tiff|image\/x\-cmu\-raster|image\/x\-cmx|image\/x\-icon|image\/x\-portable\-anymap|image\/x\-portable\-bitmap|image\/x\-portable\-graymap|image\/x\-portable\-pixmap|image\/x\-rgb|image\/x\-xbitmap|image\/x\-xpixmap|image\/x\-xwindowdump)$/i; if(input.files.length == 0) { return false; } var file = input.files[0]; //过滤非图片 if(!filter.test(file.type)) { return false; } //文件读取完成之后,目标元素的result属性会包含有一个data: URL字符串代表文件内容 reader.addEventListener("load", function(evt){ document.getElementById("uploadPreview").src = evt.target.result; }, false); reader.readAsDataURL(file); //读取文件内容 } btn.addEventListener("click", uploader, false); //点击上传 input.addEventListener("change", preview, false); //选取文件之后,预览图片 } }
然后是上传服务器端的脚步upload.php
:
<?php var_dump($_FILES);
很简单,我们只要打印出上传信息就足够了。
如果在本地测试的话,速度太快,你可能会看不见上传进度百分比的变化。
本来链接:https://360us.net/article/26.html