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 相关文章推荐
你可能不再需要JQUERY
Mar 09 Javascript
JavaScript学习笔记(十七)js 优化
Feb 04 Javascript
js创建数据共享接口——简化框架之间相互传值
Oct 23 Javascript
浅谈checkbox的一些操作(实战经验)
Nov 20 Javascript
JavaScript设计模式之观察者模式(发布者-订阅者模式)
Sep 24 Javascript
简述AngularJS的控制器的使用
Jun 16 Javascript
jQuery实现新消息在网页标题闪烁提示
Jun 23 Javascript
js实现3D图片逐张轮播幻灯片特效代码分享
Sep 09 Javascript
利用css+原生js制作简单的钟表
Apr 07 Javascript
Node.js 使用命令行工具检查更新
Jun 08 Javascript
vue axios用法教程详解
Jul 23 Javascript
jQuery点击页面其他部分隐藏下拉菜单功能
Nov 27 jQuery
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数组合并与拆分实例分析
2015/06/12 PHP
CI框架支持$_GET的两种实现方法
2016/05/18 PHP
php 实现301重定向跳转实例代码
2016/07/18 PHP
dojo随手记 gird组件引用
2011/02/24 Javascript
深入理解JavaScript系列(28):设计模式之工厂模式详解
2015/03/03 Javascript
jquery简单实现幻灯片的方法
2015/08/03 Javascript
基于jquery实现页面滚动时顶部导航显示隐藏
2020/04/20 Javascript
原生js编写autoComplete插件
2016/04/13 Javascript
微信JS-SDK选取手机照片上传功能
2017/04/21 Javascript
五步轻松实现zTree的使用
2017/11/01 Javascript
使用svg实现动态时钟效果
2018/07/17 Javascript
微信小程序外卖选购页实现切换分类与数量加减功能案例
2019/01/15 Javascript
微信小程序wepy框架学习和使用心得详解
2019/05/24 Javascript
javascript(基于jQuery)实现鼠标获取选中的文字示例【测试可用】
2019/10/26 jQuery
[47:18]完美世界DOTA2联赛循环赛 IO vs FTD BO2第一场 11.05
2020/11/06 DOTA
Python基于贪心算法解决背包问题示例
2017/11/27 Python
python实现list由于numpy array的转换
2018/04/04 Python
详谈python中冒号与逗号的区别
2018/04/18 Python
基于Python List的赋值方法
2018/06/23 Python
Python两台电脑实现TCP通信的方法示例
2019/05/06 Python
基于MATLAB和Python实现MFCC特征参数提取
2019/08/13 Python
pytorch中tensor.expand()和tensor.expand_as()函数详解
2019/12/27 Python
Python库skimage绘制二值图像代码实例
2020/04/10 Python
PyQt5实现画布小程序
2020/05/30 Python
基于python的opencv图像处理实现对斑马线的检测示例
2020/11/29 Python
澳大利亚家具和家居用品在线:BROSA
2017/11/02 全球购物
Oracle的内存结构(Memory structures)
2015/06/10 面试题
网络工程专业毕业生推荐信
2013/10/28 职场文书
《恐龙》教学反思
2014/04/27 职场文书
应届生求职信范文
2014/06/30 职场文书
大学生联谊活动策划书(光棍节)
2014/10/10 职场文书
党的群众路线教育实践活动心得体会(企业)
2014/11/03 职场文书
离职报告格式
2014/11/04 职场文书
2015年教学管理工作总结
2015/05/20 职场文书
2015年小学数学教师个人工作总结
2015/05/25 职场文书
小英雄雨来观后感
2015/06/09 职场文书