我们能够如此简单的实现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