Nodejs+express+html5 实现拖拽上传_node.js(2)
uploader对象主要是对html5提供的原生api进行简单的封装。uploaderFactory提供一个简单的接口,使用它可以像jquery的ajax方法一样完成,文件上传调用。html5中提供的文件上传的支持,是在原来XMLHttpRequest基础之上扩展一些属性和方法,提供了FormData对象,来支持文件上传操作。
文件上传队列(uploaderQueue.js)也是一个比较重要的对象,它包括两个对象一个是Queue,文件队列对象,主要负责管理文件队列的增删改查询等操作,另一个对象是UploadEngine,文件上传引擎,它的功能主要是负责从文件队列中取出文件对象,调用uploader对象上传文件,然后更新文件队列中的文件状态。Queue以及UploadEngine都是单例对象。
首先来看下文件队列对象:
(function (upladerQueue) {
var Status = {
Ready: 0,
Uploading: 1,
Complete: 2
}
var _self = null;
var instance = null;
function Queue() {
this._datas = [];
this._curSize = 0;//当前长度
_self = this;
}
Queue.prototype = {
add: function (data) {
var key = new Date().getTime();
this._datas.push({key: key, data: data, status: Status.Ready});
this._curSize = this._datas.length;
return key;
},
remove: function (key) {
var index = this._getIndexByKey(key);
this._datas.splice(index, 1);
this._curSize = this._datas.length;
},
get: function (key) {
var index = this._getIndexByKey(key);
return index != -1 ? this._datas[index].data : null;
},
clear: function () {
this._datas = [];
this._curSize = this._datas.length;
},
size: function () {
return this._curSize;
},
setItemStatus: function (key, status) {
var index = this._getIndexByKey(key);
if (index != -1) {
this._datas[index].status = status;
}
},
nextReadyingIndex: function () {
for (var i = 0; i < this._datas.length; i++) {
if (this._datas[i].status == Status.Ready) {
return i;
}
}
return -1;
},
getDataByIndex: function (index) {
if (index < 0) {
return null;
}
return this._datas[index];
},
_getIndexByKey: function (key) {
for (var i = 0; i < this._datas.length; i++) {
if (this._datas[i].key == key) {
return i;
}
}
return -1;
}
};
function getInstace() {
if (instance === null) {
instance = new Queue();
return instance;
} else {
return instance;
}
}
upladerQueue.Queue = getInstace();
upladerQueue.UploadStatus = Status;
})(window.uploaderQueue);
上传文件队列使用一个数组管理每个文件对象信息,每个文件对象有key,data,status三个属性,该对象主要负责文件对象的增加、删除、更新、查找的功能。
上传文件队列中另一个比较重要的对象是上传引擎对象(uploadEngine.js)
(function (upladerQueue) {
var instance = null;
var _self;
function uploadEngine() {
this._url = null;
this._curUploadingKey = -1;//标志
this.uploadStatusChanged = {};
this.uploadItemProgress={};
_self = this;
}
uploadEngine.prototype = {
setUrl: function (url) {
this._url = url;
},
run: function () {
if (this._curUploadingKey === -1 && this._url) {
this._startUpload();
}
},
_startUpload: function () {
_self = this;
var index = upladerQueue.Queue.nextReadyingIndex();
if (index != -1) {
this._uploadItem(index);
} else {
this._curUploadingKey = -1;
return null;
}
},
_uploadItem: function (index) {
var data = upladerQueue.Queue.getDataByIndex(index).data;
_self = this;
this._readyUploadItem(index);
var upload = uploaderFactory.send(this._url, null, data.files, function (status, data) {
_self._completedUploadItem.call(_self, status, data);
});
this._uploadItemProgress(upload);
},
_uploadItemProgress: function (upload) {
upload.onprogress = function (e) {
_self.uploadItemProgress(_self._curUploadingKey,e);
}
},
_readyUploadItem: function (index) {
this._curUploadingKey = upladerQueue.Queue.getDataByIndex(index).key;
if (typeof this.uploadStatusChanged === 'function') {
this.uploadStatusChanged(this._curUploadingKey, upladerQueue.UploadStatus.Uploading);
}
upladerQueue.Queue.setItemStatus(this._curUploadingKey, upladerQueue.UploadStatus.Uploading);
},
_completedUploadItem: function (status, data) {
if (typeof this.uploadStatusChanged === 'function') {
this.uploadStatusChanged(this._curUploadingKey, upladerQueue.UploadStatus.Complete);
}
upladerQueue.Queue.setItemStatus(this._curUploadingKey, upladerQueue.UploadStatus.Complete);
this._startUpload();
}
};
function getInstace() {
if (instance === null) {
instance = new uploadEngine();
}
return instance;
}
upladerQueue.Engine = getInstace();
})(window.uploaderQueue);






