FireFox浏览器使用Javascript上传大文件
本程序是利用3.x的Firefox浏览器可以读取本地文件的特性,实现通过xmlHttPRequest上传大文件功能,并在可以上传过程中动态显示上传进度。略加修改,并与服务器端配合,可以实现断点续传等诸多功能。 代码如下: /* * 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 } /* 以下是服务器端php代码 代码如下: /* * 获取输入信息 */ $b64 = file_get_contents("php://input"); /* * 获取头部信息 */ $headers = getallheaders(); $fileName = $headers['#FILE_NAME#']; $contentType = $headers['#CONTENT_TYPE#']; /* /* 客户端完整代码 代码如下: 2 3 4 5 6 7 8 9 相关内容
|