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验证图片类型(扩展名)的函数分享
May 05 Javascript
js纯数字逐一停止显示效果的实现代码
Mar 16 Javascript
基于JS实现导航条flash导航条
Jun 17 Javascript
微信小程序商城项目之侧栏分类效果(1)
Apr 17 Javascript
详解在Angular项目中添加插件ng-bootstrap
Jul 04 Javascript
分享19个JavaScript 有用的简写写法
Jul 07 Javascript
详解webpack性能优化——DLL
Oct 20 Javascript
Redux实现组合计数器的示例代码
Jul 04 Javascript
jQuery实现的监听导航滚动置顶状态功能示例
Jul 23 jQuery
Javascript中parseInt的正确使用方式
Oct 17 Javascript
jquery 遍历hash操作示例【基于ajax交互】
Oct 12 jQuery
vue 路由meta 设置导航隐藏与显示功能的示例代码
Sep 04 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
PHP5.2下chunk_split()函数整数溢出漏洞 分析
2007/06/06 PHP
用PHP即时捕捉PHP中的错误并发送email通知的实现代码
2013/01/19 PHP
ThinkPHP模板比较标签用法详解
2014/06/30 PHP
PHP实现远程下载文件到本地
2015/05/17 PHP
Laravel 5.3 学习笔记之 错误&amp;日志
2016/08/28 PHP
thinkPHP框架自动填充原理与用法分析
2018/04/03 PHP
Javascript 面向对象 重载
2010/05/13 Javascript
浅析jQuery1.8的几个小变化
2013/12/10 Javascript
分享28款免费实用的 JQuery 图片和内容滑块插件
2014/12/15 Javascript
javascript中的altKey 和 Event属性大全
2015/11/06 Javascript
基于jQuery实现网页打印功能
2015/12/01 Javascript
Node.js服务器环境下使用Mock.js拦截AJAX请求的教程
2016/05/23 Javascript
利用AngularJs实现京东首页轮播图效果
2016/09/08 Javascript
Javascript的动态增加类的实现方法
2016/10/20 Javascript
20行js代码实现的贪吃蛇小游戏
2017/06/20 Javascript
jQuery实现右侧抽屉式在线客服功能
2017/12/25 jQuery
ios设备中angularjs无法改变页面title的解决方法
2018/09/13 Javascript
JavaScript链式调用实例浅析
2018/12/19 Javascript
JavaScript怎样在删除前添加确认弹出框?
2019/05/27 Javascript
使用Vue CLI创建typescript项目的方法
2019/08/09 Javascript
JSON stringify方法原理及实例解析
2020/10/23 Javascript
原生js实现自定义消息提示框
2020/11/19 Javascript
[38:38]完美世界DOTA2联赛PWL S3 access vs Rebirth 第二场 12.17
2020/12/18 DOTA
python交互式图形编程实例(三)
2017/11/17 Python
python实现简单图片物体标注工具
2019/03/18 Python
Python闭包和装饰器用法实例详解
2019/05/22 Python
python 图片二值化处理(处理后为纯黑白的图片)
2019/11/01 Python
Python实现socket非阻塞通讯功能示例
2019/11/06 Python
Python ArgumentParse的subparser用法说明
2020/04/20 Python
Python Charles抓包配置实现流程图解
2020/09/29 Python
纯CSS实现菜单、导航栏的3D翻转动画效果
2014/04/23 HTML / CSS
美国演唱会订票网站:Ticketmaster美国
2017/10/05 全球购物
一加手机美国官方网站:OnePlus美国
2019/09/19 全球购物
POS解决方案:MUNBYN(热敏打印机、条形码扫描仪)
2020/06/09 全球购物
体育系毕业生自荐信
2014/06/28 职场文书
七年级地理教学计划
2015/01/22 职场文书