File, FileReader 和 Ajax 文件上传实例分析(php)


Posted in Javascript onApril 27, 2011

File FileReader 可以干什么?
Ajax文件上传例子
FileReader 对象可以读取文件的 Base64编码数据(readAsDataURL),2进制字符串(readAsBinaryString),文本(readAsText)并且都是异步的。
对了,Email拖拽附件上传就可以利用 FileReader 配合 Ajax 完成。

File 对象
File对象可以从 input[type=file].files 数组,和拖拽事件 event.dataTransfer.files 中获取到。
第一张图是 Chrome 下的 File 对象,第2个图是Firefox下的File对象。Firefox下会多几个方法,注意这里的读取数据方法是同步的。

File, FileReader 和 Ajax 文件上传实例分析(php)

File, FileReader 和 Ajax 文件上传实例分析(php)
FileReader 对象
这是用来读取文件数据的(并且是异步的)。下面是一个简单的代码(file对象用上面的方法取得)

var fileReader = new FileReader(); 
fileReader.onloadend = function(){ 
console.log(this.readyState); // 这个时候 应该是 2 
console.log(this.result); 读取完成回调函数,数据保存在result中 
} 
fileReader.readAsBinaryString(file);// 开始读取2进制数据 异步 参数为file 对象 
//fileReader.readAsDataURL(file); // 读取Base64 
//fileReader.readAsText(file);//读取文本信息

可以运行下面简单的例子(chrome 和 firefox 有效)
<!DOCTYPE html > 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>html5 File and FileReader</title> 
<link href="html/ui.css" _mce_href="html/ui.css" rel="stylesheet" /> 
</head> 
<body> 
<style type="text/css"><!-- 
.box{background:#f8f8f8;border:1px solid #CCC;padding:10px;-webkit-box-shadow:#000 0px 0px 4px;-moz-box-shadow:#000 0px 0px 4px; 
-webkit-border-radius:2px;font-family: 'Segoe UI', Calibri, 'Myriad Pro', Myriad, 'Trebuchet MS', Helvetica, Arial, sans-serif; 
} 
.bl{ font-weight:700;} 
.dl{ padding:10px; border-top:1px dotted #999;} 
.dl dd{ padding:0; margin:0;} 
.log{border:1px solid #CCC; background:#f8f8f8; width:200px; position:absolute; right:10px; top:10px;} 
.log li{border:1p dotted #CCC;word-wrap:break-word;word-break:break-all; margin:0px; padding:0;} 
.log ul{margin:0px; padding:0; list-style:none;} 
--></style><style type="text/css" _mce_bogus="1"><!-- 
.box{background:#f8f8f8;border:1px solid #CCC;padding:10px;-webkit-box-shadow:#000 0px 0px 4px;-moz-box-shadow:#000 0px 0px 4px; 
-webkit-border-radius:2px;font-family: 'Segoe UI', Calibri, 'Myriad Pro', Myriad, 'Trebuchet MS', Helvetica, Arial, sans-serif; 
} 
.bl{ font-weight:700;} 
.dl{ padding:10px; border-top:1px dotted #999;} 
.dl dd{ padding:0; margin:0;} 
.log{border:1px solid #CCC; background:#f8f8f8; width:200px; position:absolute; right:10px; top:10px;} 
.log li{border:1p dotted #CCC;word-wrap:break-word;word-break:break-all; margin:0px; padding:0;} 
.log ul{margin:0px; padding:0; list-style:none;} 
--></style> 
<div class="box" id="baseInfo"> 
<h2>(把图片拖拽到这里)利用 FileReader 获取文件 base64 编码</h2> 
<div></div> 
</div> 
<div class="log"> 
<ul id="log"> 
</ul> 
</div> 
<script type="text/javascript" ><!-- 
(function(){ 
window.dataValue = 0; 
var html = ' <dl class="dl">\ 
<dd>fileName: $fileName$</dd>\ 
<dd>fileType: $fileType$</dd>\ 
<dd>fileSize: $fileSize$</dd>\ 
<dd><img src="$data$" /></dd>\ 
<dd>fileBase64: <br/>\ 
<div style="width:100%; height:100px;">$fileBase64$</div>\ 
</dd>\ 
</dl>\ 
' 
var log = function(msg){ 
//console['log'](msg); 
document.getElementById('log').innerHTML += '<li>'+ msg +'</li>'; 
} var DP = function(){ 
var defConfig = { 
dropWrap : window 
} 
this.init.apply(this, [defConfig]); 
this.file = null; 
} 
DP.prototype = { 
init:function(args){ 
var dropWrap = args.dropWrap; 
var _this = this; 
dropWrap.addEventListener("dragenter", this._dragenter, false); 
dropWrap.addEventListener("dragover", this._dragover, false); 
dropWrap.addEventListener('drop', function(e){_this.readFile.call(_this,e)} , false); 
log('window drop bind--ok'); 
}, 
_dragenter:function(e){e.stopPropagation();e.preventDefault();}, 
_dragover:function(e){e.stopPropagation();e.preventDefault();}, 
readFile:function(e){ 
e.stopPropagation(); 
e.preventDefault(); 
var dt = e.dataTransfer; 
var files = dt.files; 
for(var i = 0; i< files.length;i++){ 
var HTML = html.slice(); 
HTML = this.writeHeader(files[i], HTML); 
this.read(files[i], HTML); 
} 
}, 
read:function(file, h){ 
var type = file.type; 
var reader = new FileReader(); 
reader.onprogress = function(e){ 
if (e.lengthComputable){ 
log('progress: ' + Math.ceil(100*e.loaded/file.size) +'%') 
} 
}; 
reader.onloadstart = function(e){ 
log('onloadstart: ok'); 
}; 
reader.onloadend = function(e){ 
var _result = e.target.result; 
//console['log'](e.target); 
log('Data URI--ok'); 
var d = document.createElement('div'); 
h = h.replace('$fileBase64$', _result); 
if(/image/.test(file.type)){ 
h = h.replace('$data$',_result); 
} 
d.innerHTML = h; 
document.getElementById('baseInfo').appendChild(d); 
}; 
reader.readAsDataURL(file); // base 64 编码 
return; 
}, 
writeHeader:function(file, h){ 
log(file.fileName + '+' + (file.size/1024)); 
return h.replace('$fileName$', file.fileName).replace("$fileSize$",(file.size/1024)+'KB').replace("$fileType$",file.type); 
} 
} 
new DP(); 
})() 
// --></script> 
</body> 
</html>

如何实现异步文件上传
有了File FileReader 对象的支持,异步文件上传将变得简单。(以前都会把form提交到iframe来实现)
1:取得File对象
2:读取2进制数据
3:模拟HTTP请求,把数据发送出去(这里通常比较麻烦)
在forefox下使用 XMLHttpRequest 对象的 sendAsBinary 方法发送数据;
4:完美实现
遇到的问题
目前仅有 firefox 可以正确上传文件。(Chrome也可以采google.gears上传)
对于从firefox和chrome下读取到的文件数据好像不一样(不知道是否是调试工具的原因)
Chrome以及其他高级浏览器没有 sendAsBinary 方法 只能使用 send 方法发送数据,有可能是上面的原因导致无法正确上传。(经过测试普通文本文件可以正确上传)
如果你有兴趣?
下载这个PHP环境的测试程序,研究下如何实现其他浏览器的文件上传  
Javascript 相关文章推荐
Javascript !!的作用
Dec 04 Javascript
Jquery 扩展方法
May 06 Javascript
JQuery为textarea添加maxlength属性并且兼容IE
Apr 25 Javascript
JavaScript组件焦点与页内锚点间传值的方法
Feb 02 Javascript
Javascript中的匿名函数与封装介绍
Mar 15 Javascript
JavaScript Split()方法
Dec 18 Javascript
Bootstrap轮播插件中图片变形的终极解决方案 使用jqthumb.js
Jul 10 Javascript
javascript深拷贝和浅拷贝详解
Feb 14 Javascript
彻底学会Angular.js中的transclusion
Mar 12 Javascript
JavaScript Canvas实现验证码
Aug 02 Javascript
JavaScript事件对象深入详解
Dec 30 Javascript
微信小程序实现炫酷的弹出式菜单特效
Jan 28 Javascript
JavaScript中获取未知对象属性的代码
Apr 27 #Javascript
JavaScript之HTMLCollection接口代码
Apr 27 #Javascript
利用jQuery操作对象数组的实现代码
Apr 27 #Javascript
jquery.cookie.js 操作cookie实现记住密码功能的实现代码
Apr 27 #Javascript
jquery调用asp.net 页面后台的实现代码
Apr 27 #Javascript
jQuery Ajax方法调用 Asp.Net WebService 的详细实例代码
Apr 27 #Javascript
Javascript实现仿WebQQ界面的“浮云”兼容 IE7以上版本及FF
Apr 27 #Javascript
You might like
php inc文件使用的风险和注意事项
2013/11/12 PHP
ThinkPHP实现简单登陆功能
2017/04/28 PHP
jQuery队列控制方法详解queue()/dequeue()/clearQueue()
2010/12/02 Javascript
了解了这些才能开始发挥jQuery的威力
2013/10/10 Javascript
js实现数字每三位加逗号的方法
2015/02/05 Javascript
JavaScript Function函数类型介绍
2015/04/08 Javascript
JS选项卡动态替换banner图片路径的方法
2015/05/11 Javascript
简介BootStrap model弹出框的使用
2016/04/27 Javascript
手机Web APP如何实现分享多平台功能
2016/08/19 Javascript
JS实现复选框的全选和批量删除功能
2017/04/05 Javascript
bootstrap轮播图示例代码分享
2017/05/17 Javascript
js判断用户是输入的地址请求的路径(实例讲解)
2017/07/18 Javascript
vue几个常用跨域处理方式介绍
2018/02/07 Javascript
layui实现数据表格点击搜索功能
2020/03/26 Javascript
js神秘的电报密码 哈弗曼编码实现
2019/09/10 Javascript
vue项目中锚点定位替代方式
2019/11/13 Javascript
[02:08]DOTA2英雄基础教程 马格纳斯
2014/01/17 DOTA
用Python展示动态规则法用以解决重叠子问题的示例
2015/04/02 Python
在Python中封装GObject模块进行图形化程序编程的教程
2015/04/14 Python
python3.x上post发送json数据
2018/03/04 Python
python如何让类支持比较运算
2018/03/20 Python
如何优雅地改进Django中的模板碎片缓存详解
2018/07/04 Python
Python内置random模块生成随机数的方法
2019/05/31 Python
python3.6根据m3u8下载mp4视频
2019/06/17 Python
Python基于BeautifulSoup和requests实现的爬虫功能示例
2019/08/02 Python
Python使用python-docx读写word文档
2019/08/26 Python
Python 通过正则表达式快速获取电影的下载地址
2020/08/17 Python
CSS3五个技巧给你的网站带来出色的效果
2009/04/02 HTML / CSS
HTML5之多线程(Web Worker)
2019/01/02 HTML / CSS
Nike瑞士官网:Nike CH
2021/01/18 全球购物
工商管理实习自我鉴定
2013/09/28 职场文书
餐饮采购员岗位职责
2014/03/15 职场文书
反四风个人对照检查材料
2014/09/26 职场文书
酒店管理专业毕业生自我鉴定
2014/09/29 职场文书
Redis集群节点通信过程/原理流程分析
2022/03/18 Redis
mysql中关键词exists的用法实例详解
2022/06/10 MySQL