本程序是利用3.x的Firefox浏览器可以读取本地文件的特性,实现通过xmlHttPRequest上传大文件功能,并在可以上传过程中动态显示上传进度。略加修改,并与服务器端配合,可以实现断点续传等诸多功能。
本例主要是研究FireFox的file-input节点的一些特性,其他客户端应用,如Flash、Sliverlight等,在实现客户端大文件上传时,在数据传输与服务器端存储等方面,与本例的思路基本一致。
注意:文件体积似乎有临界点,但这个临界点是多少尚未确认。建议不要用此方法上传超过100M的文件。
以下是客户端javascript代码
复制代码 代码如下:
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;
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.');
}
this.packageSize = conf.packageSize || 102400;
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,
length : -1,
checkError : function(){
if(this.errMsg.length > 0){
typeof this.onError == 'function' && this.onError(this.errMsg);
return;
}
},
createSender : function(){
var xhr = new XMLHttpRequest();
xhr.open('POST', this.url, true);
var _ = this;
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
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);
this.position += this.currentData.length;
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') {
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(
{
file : fileID,
url : 'UPLOADER.php',
packageSize : '200000',
onError : function(arrMsg){
alert(arrMsg.join('rn'));
sender = null;
delete sender;
},
onSending : function(sd, xhr){
var per = sd.percent();
document.getElementById('Message').innerHTML = per + '% ';
if(parseInt(per) == 100){ alert('服务器端接收完成'); }
},
onSendFinished : function(){
alert('本地数据发送完成');
}
}
);
sender.send();
}
以下是服务器端php代码
复制代码 代码如下:
$b64 = file_get_contents("php://input");
$headers = getallheaders();
$fileName = $headers['#FILE_NAME#'];
$contentType = $headers['#CONTENT_TYPE#'];
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


