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 相关文章推荐
执行iframe中的javascript方法
Oct 07 Javascript
JQuery 入门实例1
Jun 25 Javascript
Jquery上传插件 uploadify v3.1使用说明
Jun 18 Javascript
javascript中强制执行toString()具体实现
Apr 27 Javascript
jquery easyui combobox模糊过滤(示例代码)
Nov 30 Javascript
Jquery 全选反选实例代码
Nov 19 Javascript
jQuery实现Table表格隔行变色及高亮显示当前选择行效果示例
Feb 14 Javascript
Vue的Flux框架之Vuex状态管理器
Jul 30 Javascript
React Native AsyncStorage本地存储工具类
Oct 24 Javascript
微信小程序中为什么使用var that=this
Aug 27 Javascript
如何在Express4.x中愉快地使用async的方法
Nov 18 Javascript
vue 使用 sortable 实现 el-table 拖拽排序功能
Dec 26 Vue.js
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
很温暖很温暖的Lester Young
2021/03/03 冲泡冲煮
使用TinyButStrong模板引擎来做WEB开发
2007/03/16 PHP
php生成图形(Libchart)实例
2013/11/06 PHP
ThinkPHP模板中判断volist循环的最后一条记录的验证方法
2014/07/01 PHP
PHP房贷计算器实例代码,等额本息,等额本金
2017/04/01 PHP
PHP更安全的密码加密机制Bcrypt详解
2017/06/18 PHP
PHP常用的类封装小结【4个工具类】
2019/06/28 PHP
取键盘键位ASCII码的网页
2007/07/30 Javascript
jQuery方法简洁实现隔行换色及toggleClass的使用
2013/03/15 Javascript
JavaScript charCodeAt方法入门实例(用于取得指定位置字符的Unicode编码)
2014/10/17 Javascript
JS实现超简单的鼠标拖动效果
2015/11/02 Javascript
JavaScript编程的单例设计模讲解
2015/11/10 Javascript
用JS实现图片轮播效果代码(一)
2016/06/26 Javascript
使用Angular.js开发的注意事项
2016/10/19 Javascript
表格展示利器 Bootstrap Table实例代码
2017/09/06 Javascript
Node.js 使用AngularJS的方法示例
2018/05/11 Javascript
Layui给数据表格动态添加一行并跳转到添加行所在页的方法
2018/08/20 Javascript
使用vue脚手架(vue-cli)搭建一个项目详解
2019/05/09 Javascript
使用Python的PEAK来适配协议的教程
2015/04/14 Python
Python实现简单的代理服务器
2015/07/25 Python
python编程通过蒙特卡洛法计算定积分详解
2017/12/13 Python
python调用系统ffmpeg实现视频截图、http发送
2018/03/06 Python
基于PyQt4和PySide实现输入对话框效果
2019/02/27 Python
基于Python实现剪切板实时监控方法解析
2019/09/11 Python
Python如何省略括号方法详解
2020/03/21 Python
基于PyQT实现区分左键双击和单击
2020/05/19 Python
python 删除excel表格重复行,数据预处理操作
2020/07/06 Python
戴尔新加坡官网:Dell Singapore
2020/12/13 全球购物
金额转换,阿拉伯数字的金额转换成中国传统的形式如:(¥1011)-> (一千零一拾一元整)输出
2015/05/29 面试题
儿科主治医生个人求职信
2013/09/23 职场文书
求职自荐信格式
2013/12/04 职场文书
法律专业学生的自我评价
2014/02/07 职场文书
中药专业毕业自荐书范文
2014/02/08 职场文书
2014年英语工作总结
2014/12/20 职场文书
红白喜事主持词
2015/07/06 职场文书
八年级地理课件资料及考点知识分享
2019/08/30 职场文书