FireFox浏览器使用Javascript上传大文件 |
本文标签: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#]; /* /* 客户端完整代码 复制代码 代码如下: <!DOCTYPE HTML> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 5 <title>FireFoxFileSender - !! ONLY FOR FireFox !!</title> 6 </head> 7 8 <body> 9 <script type="text/Javascript"> 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 |