热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

FireFox浏览器使用Javascript上传大文件_php实例

本程序是利用3.x的Firefox浏览器可以读取本地文件的特性,实现通过xmlHttPRequest上传大文件功能。
本程序是利用3.x的Firefox浏览器可以读取本地文件的特性,实现通过xmlHttPRequest上传大文件功能,并在可以上传过程中动态显示上传进度。略加修改,并与服务器端配合,可以实现断点续传等诸多功能。
本例主要是研究FireFox的file-input节点的一些特性,其他客户端应用,如Flash、Sliverlight等,在实现客户端大文件上传时,在数据传输与服务器端存储等方面,与本例的思路基本一致。
注意:文件体积似乎有临界点,但这个临界点是多少尚未确认。建议不要用此方法上传超过100M的文件。
以下是客户端Javascript代码

代码如下:


/*
* FireFoxFileSender version 0.0.0.1
* by MK winnie_mk(a)126.com
*
* 【本程序仅限于FireFox3.x版本,其他浏览器是否可以运行未做测试。】
* 【测试通过:FireFox 3.6.8 / Apache/2.2.11 (Win32) php/5.2.6 】
* ******************************************************************************
* 本程序是利用3.x的FireFox浏览器可以读取本地文件的特性
* 实现通过xmlhttpRequest上传大文件功能
* 并在可以上传过程中动态显示上传进度
* 略加修改,并与服务器端配合,可以实现断点续传等诸多功能
* 本例主要是研究FireFox的file-input节点的一些特性
* 其他客户端应用,如Flash、Sliverlight等,在实现客户端大文件上传时
* 在数据传输与服务器端存储等方面,与本例的思路基本一致
* 注意:文件体积似乎有个临界点,但这个临界点是多少尚未确认。建议不要用此方法上传超过100M的文件。
* ******************************************************************************
*/
function FireFoxFileSender(config){
var cOnf= config || {};
/*
* 错误信息队列
*/
this.errMsg = [];
/*
* 判断各参数是否齐备
*/
this.f = typeof conf.file == 'string' ?
    document.getElementById(conf.file) : conf.file;
if(!this.f){ this.errMsg.push('Error: Not set the input file.'); }
else if(this.f.files.length <1){ this.errMsg.push('Error: Not select a file.'); }
else {
this.fileName = this.f.value;
/*
* 在尝试直接发送二进制流时失败,改用发送base64编码数据。
*/
this.data = (this.data = this.f.files[0].getAsDataURL())
      .substr(this.data.indexOf(',') + 1);
this.length = this.data.length;
/*
* 文件实际大小
*/
this.fileSize = this.f.files[0].fileSize;
/*
* 文件类型
*/
this.cOntentType= this.f.files[0].fileType;
}
/*
* 服务器端接收地址
*/
this.url = conf.url;
if(!this.url){
    this.errMsg.push('Error: Not set the instance url to send binary.');
  }
/*
* 发送数据包的大小。默认100kb
*/
this.packageSize = conf.packageSize || 102400;
/*
* 每次发送数据包大小应为4的倍数,确保服务器端转换base64编码正确。
*/
if(this.packageSize % 4 != 0)
    this.packageSize = parseInt(this.packageSize / 4) * 4;

this.OnSendFinished= conf.onSendFinished || null;
this.OnSending= conf.onSending || null;
this.OnError= conf.onError || null;
}
FireFoxFileSender.prototype = {
/*
* 记录当前发送的数据
*/
currentData : null,
/*
* 记录读取位置
*/
position : 0,
/*
* 数据大小。该值为base64字符串的长度。
*/
length : -1,
/*
* 检查错误队列,尝试触发onError事件
*/
checkError : function(){
if(this.errMsg.length > 0){
/*
* 触发onError事件
*/
typeof this.OnError== 'function' && this.onError(this.errMsg);
return;
}
},
/*
* 创建XMLHttpRequest
*/
createSender : function(){
var xhr = new XMLHttpRequest();
xhr.open('POST', this.url, true);
var _ = this;
xhr.Onreadystatechange= function(){
/*
* 当服务器段响应正常,则循环读取发送。
*/
if(xhr.readyState == 4 && xhr.status == 200){
/*
* 触发onSending事件
*/
if(typeof _.OnSending== 'function') _.onSending(_, xhr);
/*
* 延时发送下一次请求,否则服务器负担过重
*/
var send = setTimeout(function(){
_.send();
clearTimeout(send);
send = null;
}, 100);
}
}
return xhr;
},
/*
* 发送数据
*/
send : function(){
this.checkError();
/*
* 获取当前要发送的数据
*/
this.currentData = this.data.substr(this.position, this.packageSize);
/*
* 更改postion,模拟数据流移位
*/
this.position += this.currentData.length;
/*
* 如果读取字符串长度大于0,则发送该数据
* 否则触发onSendFinished事件
*/
if(this.currentData.length > 0) {
var xhr = this.createSender();
/*
* 自定义头部信息,通知服务器端文件相关信息
* 实际应用时可修改此部分。
*/
xhr.setRequestHeader('#FILE_NAME#', this.fileName);
xhr.setRequestHeader('#FILE_SIZE#', this.length);
xhr.setRequestHeader('#CONTENT_TYPE#', this.contentType);

xhr.send(this.currentData);
} else if(typeof this.OnSendFinished== 'function') {
/*
* 触发onSendFinished事件
*/
this.onSendFinished(this);
}
},
/*
* 计算已发送数据百分比
*/
percent : function(){
if(this.length <= 0 ) return -1;
return Math.round((this.position / this.length) * 10000) / 100;
},
onSendFinished : null, //该事件是以本地数据发送完成为触发,并不是服务器端返回的完成信息。
onSending : null,
onError : null
}

/*
* 上传按钮事件
*/
function send(fileID){
var sender = new FireFoxFileSender(
/*
* 上传配置文件
*/
{
/*
* input file 元素,可以是dom节点,也可以是id的字符串值
*/
file : fileID,
/*
* 接收上传数据的服务器端地址
*/
url : 'UPLOADER.php',
/*
* 每次发送数据包的大小。可根据服务器具体情况更改。IIS6默认为200K
*/
packageSize : '200000',
/*
* 出现错误时触发该事件。本例仅在初始化时判断各参数是否齐备,并没有抛出发送过程中的错误。
*/
onError : function(arrMsg){
alert(arrMsg.join('\r\n'));
sender = null;
delete sender;
},
/*
* 发送过程中触发该事件。本例中主要用于显示进度。
*/
onSending : function(sd, xhr){
var per = sd.percent();
document.getElementById('Message').innerHTML = per + '% ';
/*
* 该判断是在最后一次发送结束后,通过xhr的onreadystatechange事件触发的
* 如果传输过程中没有其他错误,基本可以确定为服务器端接收完成
*/
if(parseInt(per) == 100){ alert('服务器端接收完成'); }
},
/*
* 该事件仅仅为【本地数据发送完成】时触发。
* 请区别本地数据发送完成和服务器端返回完成信息这两种情况
* 本例中并没有对服务器接收信息的情况做响应
* 即使服务器端没有接收和保存任何数据
* 只要确保xhr返回readyState == 4 和 status == 200
* 发送就会继续进行
* 服务器端如何返回完成信息可以通过更改接收数据页面的代码自定实现
* 然后通过对xhr.responseText的值来做判断
*/
onSendFinished : function(){
alert('本地数据发送完成');
}
}
);
sender.send();
}


以下是服务器端php代码

代码如下:


/*
* 获取输入信息
*/
$b64 = file_get_contents("php://input");
/*
* 获取头部信息
*/
$headers = getallheaders();
$fileName = $headers['#FILE_NAME#'];
$cOntentType= $headers['#CONTENT_TYPE#'];

/*
* 做一些判断和处理...
*/

/*
* 以下是服务器端对发送数据的简单响应
* - 假如有数据被post过来 则输出对base64转换为二进制流后,二进制流的长度
* - 否则输出0
* 这仅仅是一个例子,并且在js端没有接收这个信息
* 同样,也可以采用在header中写入反馈信息等等方法
* 回馈信息给客户端
* 主要目的是确定上传过程中是否有其他问题出现
* 以确保上传文件完整
*/
if(!empty($b64)){
$stream = base64_decode($b64);
echo strlen($stream);
/*
* 追加方式写入文件
* 在此修改文件保存位置
*/
$file = fopen('' . $fileName , 'a');
if($file)
if(fwrite($file, $stream))
fclose($file);
} else echo '0';


客户端完整代码

代码如下:



2
3
4
5
6
7
8
9
10 /*
11 * FireFoxFileSender version 0.0.0.1
12 * by MK winnie_mk(a)126.com
13 *
14 * 【本程序仅限于FireFox3.x版本,其他浏览器是否可以运行未做测试。】
15 * 【测试通过:FireFox 3.6.8 / Apache/2.2.11 (Win32) PHP/5.2.6 】
16 * *********************************************************************************
17 * 本程序是利用3.x的FireFox浏览器可以读取本地文件的特性
18 * 实现通过XMLHttpRequest上传大文件功能
19 * 并在可以上传过程中动态显示上传进度
20 * 略加修改,并与服务器端配合,可以实现断点续传等诸多功能
21 * 本例主要是研究FireFox的file-input节点的一些特性
22 * 其他客户端应用,如Flash、Sliverlight等,在实现客户端大文件上传时
23 * 在数据传输与服务器端存储等方面,与本例的思路基本一致
24 * 注意:文件体积似乎有个临界点,但这个临界点是多少尚未确认。建议不要用此方法上传超过100M的文件。
25 * *********************************************************************************
26 */
27 function FireFoxFileSender(config){
28 var cOnf= config || {};
29 /*
30 * 错误信息队列
31 */
32 this.errMsg = [];
33 /*
34 * 判断各参数是否齐备
35 */
36 this.f = typeof conf.file == 'string' ? document.getElementById(conf.file) : conf.file;
37 if(!this.f){ this.errMsg.push('Error: Not set the input file.'); }
38 else if(this.f.files.length <1){ this.errMsg.push('Error: Not select a file.'); }
39 else {
40 this.fileName = this.f.value;
41 /*
42 * 在尝试直接发送二进制流时失败,改用发送base64编码数据。
43 */
44 this.data = (this.data = this.f.files[0].getAsDataURL()).substr(this.data.indexOf(',') + 1);
45 this.length = this.data.length;
46 /*
47 * 文件实际大小
48 */
49 this.fileSize = this.f.files[0].fileSize;
50 /*
51 * 文件类型
52 */
53 this.cOntentType= this.f.files[0].fileType;
54 }
55 /*
56 * 服务器端接收地址
57 */
58 this.url = conf.url;
59 if(!this.url){ this.errMsg.push('Error: Not set the instance url to send binary.'); }
60 /*
61 * 发送数据包的大小。默认100kb
62 */
63 this.packageSize = conf.packageSize || 102400;
64 /*
65 * 每次发送数据包大小应为4的倍数,确保服务器端转换base64编码正确。
66 */
67 if(this.packageSize % 4 != 0) this.packageSize = parseInt(this.packageSize / 4) * 4;
68
69 this.OnSendFinished= conf.onSendFinished || null;
70 this.OnSending= conf.onSending || null;
71 this.OnError= conf.onError || null;
72 }
73 FireFoxFileSender.prototype = {
74 /*
75 * 记录当前发送的数据
76 */
77 currentData : null,
78 /*
79 * 记录读取位置
80 */
81 position : 0,
82 /*
83 * 数据大小。该值为base64字符串的长度。
84 */
85 length : -1,
86 /*
87 * 检查错误队列,尝试触发onError事件
88 */
89 checkError : function(){
90 if(this.errMsg.length > 0){
91 /*
92 * 触发onError事件
93 */
94 typeof this.OnError== 'function' && this.onError(this.errMsg);
95 return;
96 }
97 },
98 /*
99 * 创建XMLHttpRequest
100 */
101 createSender : function(){
102 var xhr = new XMLHttpRequest();
103 xhr.open('POST', this.url, true);
104 var _ = this;
105 xhr.Onreadystatechange= function(){
106 /*
107 * 当服务器段响应正常,则循环读取发送。
108 */
109 if(xhr.readyState == 4 && xhr.status == 200){
110 /*
111 * 触发onSending事件
112 */
113 if(typeof _.OnSending== 'function') _.onSending(_, xhr);
114 /*
115 * 延时发送下一次请求,否则服务器负担过重
116 */
117 var send = setTimeout(function(){
118 _.send();
119 clearTimeout(send);
120 send = null;
121 }, 100);
122 }
123 }
124 return xhr;
125 },
126 /*
127 * 发送数据
128 */
129 send : function(){
130 this.checkError();
131 /*
132 * 获取当前要发送的数据
133 */
134 this.currentData = this.data.substr(this.position, this.packageSize);
135 /*
136 * 更改postion,模拟数据流移位
137 */
138 this.position += this.currentData.length;
139 /*
140 * 如果读取字符串长度大于0,则发送该数据
141 * 否则触发onSendFinished事件
142 */
143 if(this.currentData.length > 0) {
144 var xhr = this.createSender();
145 /*
146 * 自定义头部信息,通知服务器端文件相关信息
147 * 实际应用时可修改此部分。
148 */
149 xhr.setRequestHeader('#FILE_NAME#', this.fileName);
150 xhr.setRequestHeader('#FILE_SIZE#', this.length);
151 xhr.setRequestHeader('#CONTENT_TYPE#', this.contentType);
152
153 xhr.send(this.currentData);
154 } else if(typeof this.OnSendFinished== 'function') {
155 /*
156 * 触发onSendFinished事件
157 */
158 this.onSendFinished(this);
159 }
160 },
161 /*
162 * 计算已发送数据百分比
163 */
164 percent : function(){
165 if(this.length <= 0 ) return -1;
166 return Math.round((this.position / this.length) * 10000) / 100;
167 },
168 onSendFinished : null, //该事件是以本地数据发送完成为触发,并不是服务器端返回的完成信息。
169 onSending : null,
170 onError : null
171 }
172
173 /*
174 * 上传按钮事件
175 */
176 function%3

推荐阅读
  • 如何实现织梦DedeCms全站伪静态
    本文介绍了如何通过修改织梦DedeCms源代码来实现全站伪静态,以提高管理和SEO效果。全站伪静态可以避免重复URL的问题,同时通过使用mod_rewrite伪静态模块和.htaccess正则表达式,可以更好地适应搜索引擎的需求。文章还提到了一些相关的技术和工具,如Ubuntu、qt编程、tomcat端口、爬虫、php request根目录等。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文介绍了使用cacti监控mssql 2005运行资源情况的操作步骤,包括安装必要的工具和驱动,测试mssql的连接,配置监控脚本等。通过php连接mssql来获取SQL 2005性能计算器的值,实现对mssql的监控。详细的操作步骤和代码请参考附件。 ... [详细]
  • 分享css中提升优先级属性!important的用法总结
    web前端|css教程css!importantweb前端-css教程本文分享css中提升优先级属性!important的用法总结微信门店展示源码,vscode如何管理站点,ubu ... [详细]
  • 目录浏览漏洞与目录遍历漏洞的危害及修复方法
    本文讨论了目录浏览漏洞与目录遍历漏洞的危害,包括网站结构暴露、隐秘文件访问等。同时介绍了检测方法,如使用漏洞扫描器和搜索关键词。最后提供了针对常见中间件的修复方式,包括关闭目录浏览功能。对于保护网站安全具有一定的参考价值。 ... [详细]
  • Apache Shiro 身份验证绕过漏洞 (CVE202011989) 详细解析及防范措施
    本文详细解析了Apache Shiro 身份验证绕过漏洞 (CVE202011989) 的原理和影响,并提供了相应的防范措施。Apache Shiro 是一个强大且易用的Java安全框架,常用于执行身份验证、授权、密码和会话管理。在Apache Shiro 1.5.3之前的版本中,与Spring控制器一起使用时,存在特制请求可能导致身份验证绕过的漏洞。本文还介绍了该漏洞的具体细节,并给出了防范该漏洞的建议措施。 ... [详细]
  • Tomcat安装与配置教程及常见问题解决方法
    本文介绍了Tomcat的安装与配置教程,包括jdk版本的选择、域名解析、war文件的部署和访问、常见问题的解决方法等。其中涉及到的问题包括403问题、数据库连接问题、1130错误、2003错误、Java Runtime版本不兼容问题以及502错误等。最后还提到了项目的前后端连接代码的配置。通过本文的指导,读者可以顺利完成Tomcat的安装与配置,并解决常见的问题。 ... [详细]
  • 前言对于从事技术的人员来说ajax是这好东西,都会使用,而且乐于使用。但对于新手,开发一个ajax实例,还有是难度的,必竟对于他们这是新东西。leo开发一个简单的ajax实例,用的是 ... [详细]
  • JavaWeb介绍概念JavaWeb,是用Java技术来解决相关web互联网领域的技术总和。web包括:web服务器和web客户端两部分。Java在客户端的应用有javaapplet,不过使 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 如何提高PHP编程技能及推荐高级教程
    本文介绍了如何提高PHP编程技能的方法,推荐了一些高级教程。学习任何一种编程语言都需要长期的坚持和不懈的努力,本文提醒读者要有足够的耐心和时间投入。通过实践操作学习,可以更好地理解和掌握PHP语言的特异性,特别是单引号和双引号的用法。同时,本文也指出了只走马观花看整体而不深入学习的学习方式无法真正掌握这门语言,建议读者要从整体来考虑局部,培养大局观。最后,本文提醒读者完成一个像模像样的网站需要付出更多的努力和实践。 ... [详细]
  • PHP组合工具以及开发所需的工具
    本文介绍了PHP开发中常用的组合工具和开发所需的工具。对于数据分析软件,包括Excel、hihidata、SPSS、SAS、MARLAB、Eview以及各种BI与报表工具等。同时还介绍了PHP开发所需的PHP MySQL Apache集成环境,包括推荐的AppServ等版本。 ... [详细]
author-avatar
mmmm的海角_771
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有