First, the preface
File upload is a relatively common function, the traditional choice of the way to upload more trouble, you need to first click the Upload button, and then find the path to the file, and then upload. Cause a lot of problems for the user experience. HTML5 started to support the API needed to drag and drop uploads. Nodejs is also a recent and increasingly popular technology, this is the first contact Nodejs, in Nodejs development, one of the most common development framework is expess, it is a similar framework of the MVC pattern. Combined with HTML5, Nodejs Express implementation of the drag-and-drop upload function.
Ii. the popularization of basic knowledge
1. Nodejs Basic Knowledge
Nodejs Simple is a can let JS in the server can also run the development platform, Nodejs development very quickly, many domestic companies have started to use such as Taobao. The traditional Web application development platform relies on multithreading to achieve high concurrent request response. The Nodejs adopts a single thread, asynchronous Io, event-driven design model, which brings great performance improvement to Nodejs. This is also the biggest feature of Nodejs, in Nodejs, all IO operations are done through callbacks, Nodejs in the IO operation will push the IO request to an event queue, wait for the program to process, and so on processing Io, and then call the callback function to return the result.
For example, in the query database operations are as follows:
Mysql.query ("SELECT * from MyTable", function (res) {
callback (res);
});
In the above code, NODEJS does not wait for the database to return results when executing the above statement, but continues to execute the following statement. After the database gets the data, it is sent to the event loop queue and waits until the thread enters the event loop queue before executing the callback thing.
About Nodejs more knowledge, I also read for two days, do not know much. Learn more and search on the web.
The knowledge of Nodejs introduction http://www.nodebeginner.org/index-zh-cn.html http://www.jb51.net/article/48755.htm
2. Express Basic knowledge
Nodejs is a more active open source community, which has a large number of third-party development libraries, of which Express is one of the most extensive and most common framework. Nodejs is also the official recommendation of the framework. In addition to the common HTTP operations encapsulation, but also implemented routing control, template parsing support, dynamic attempts, user reply, and so on. But it's also not a one-size-fits-all framework, and most of the functionality is for HTTP encapsulation, and it's just a lightweight framework. Many features also require integration of Third-party libraries also implemented.
Exress provides a very convenient upload function support, after the file upload request, Express will receive files and the file exists in a temporary directory, and then in the route to the method, we simply copy the file from the temporary directory to our store user upload folder. In the File Upload section, the implementation of the server side is based on express this function to achieve.
3, HTML5 drag upload API
HTML5 offers a number of new features, drag-and-drop events and file uploads as one of the new features. Due to the limited space, the following focus on the implementation of the drag upload code. Do not list the HTML5 provided by the towed upload Apil, interested can refer to: http://w3school.com.cn/html5/html5_ref_eventattributes.asp http:// Www.jb51.net/html5/85977.html
Third, drag upload implementation
1, Code implementation
First look at the front-end JS file directory:
which
Uploader.js mainly realizes the encapsulation of the upload function supported by HTML5.
Uploaderqueue.js main implementation of upload file queue management, as well as file upload object, the file queue files uploaded to the server.
Uploaderapp.js main file Upload the entrance, the main implementation of the Upload window on the monitoring of drag events and drag files to promote the upload file queue, launch file upload program.
The following is a simple explanation of the core code (required), all code can be downloaded here: Fileuploader
First of all, HTML5 provided by the file upload to do a simple encapsulation uploader.js
function uploader (URL, data, files) {this._files = files;
This._data = data;
This._url = URL;
THIS._XHR = null;
This.onloadstart = {};
This.onload = {};
This.onloadend = {};
This.onprogress = {};
This.onerror = {};
This.ontimeout = {};
This.callback = {};//callback after completion of request _self = this;
} Uploader.prototype = {init:function () {if (!isvalid ()) {throw E;
} THIS._XHR = new XMLHttpRequest ();
This._bindevents ();
}, Send:function () {if (THIS._XHR = = null) {this.init ();
var formData = This._createformdata ();
This._xhr.open (' Post ', This._url, true);
This._xhr.send (FormData);
}, _bindevents:function () {_self = this;
This._xhr.upload.loadstart = function (e) {evalfunction (_self.onloadstart, E);
} this._xhr.upload.onload = function (e) {evalfunction (_self.onload, E);
};
This._xhr.upload.onloadend = function (e) {evalfunction (_self.onloadend, E); } this._xhr.upload.onprogress = fUnction (e) {evalfunction (_self.onprogress, E)};
This._xhr.upload.onerror = function (e) {evalfunction (_self.onerror, E);
};
This._xhr.upload.ontimeout = function (e) {evalfunction (_self.ontimeout, E); } This._xhr.onreadystatechange = function () {if (_self._xhr.readystate = 4) {if (typeof _self.callback = =
= ' function ') {var status = _self._xhr.status;
var data = _self._xhr.responsetext;
_self.callback (status, data);
}}}, _createformdata:function () {var formData = new FormData ();
This._adddatatoformdata (FormData);
This._addfiletoformdata (FormData);
return formData; }, _adddatatoformdata:function (FormData) {if (This._data) {for (var item in this._data) {Formdata.appen
D (item, This._data[item]); }}, _addfiletoformdata:function (FormData) {if (this._files) {for (var i = 0; i < This._files.lengt H
i++) {var file = This._files[i]; ForMdata.append (' file[' + i + '] ', this._files[i]);
}
}
}
}; View Code var uploaderfactory = {send:function (URL, data, files, callback) {var insuploader = new Uploader (URL, D
ATA, files); Insuploader.callback = function (status, Resdata) {if (typeof callback = = ' function ') {callback (status, Resdat
a);
} insuploader.send ();
return insuploader;
}
};
The uploader object is primarily a simple encapsulation of the native APIs provided by HTML5. Uploaderfactory provides a simple interface that can be used like jquery's ajax approach, file upload calls. HTML5 file upload Support, is the original XMLHttpRequest based on the extension of some properties and methods, providing Formdata objects to support file upload operations.
File Upload Queue (uploaderqueue.js) is also a relatively important object, which includes two objects, one is queue, file queuing object, mainly responsible for the management of file queues additions, deletions, and other operations, the other object is uploadengine, file upload engine, It is primarily responsible for removing file objects from the file queue, calling the uploader object to upload files, and then updating the file status in the file queue. The queue and Uploadengine are all single instances of the object.
First look at the file queue object:
(function (upladerqueue) {var Status = {ready:0, uploading:1, complete:2} var _self = null;
var instance = null;
function Queue () {this._datas = [];
This._cursize = 0;//Current length _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 = = Statu
S.ready) {return i;
}} return-1;
}, getdatabyindex:function (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 = = k
EY) {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);
Upload file queue use an array to manage each file object information, each file object has key,data,status three attribute, this object is responsible for the file object's addition, deletion, update, lookup function.
Another more important object in the upload file queue is the upload engine object (uploadengine.js)
(function (upladerqueue) {var instance = null;
var _self;
function Uploadengine () {this._url = null;
This._curuploadingkey = -1;//Flag 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.ca
ll (_self, status, data);
});
This._uploaditemprogress (upload); }, _uploAditemprogress:function (upload) {upload.onprogress = function (e) {_self.uploaditemprogress (_self._curuploadin
GKEY,E);
}, _readyuploaditem:function (index) {this._curuploadingkey = UpladerQueue.Queue.getDataByIndex (index). Key; if (typeof this.uploadstatuschanged = = = ' function ') {this.uploadstatuschanged (This._curuploadingkey, Upladerqueue.up
loadstatus.uploading);
} upladerQueue.Queue.setItemStatus (This._curuploadingkey, upladerQueue.UploadStatus.Uploading); }, _completeduploaditem:function (status, data) {if (typeof this.uploadstatuschanged = = ' function ') {THIS.UPL
Oadstatuschanged (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);
This object is relatively simple to provide a run and SetUrl method to start the upload engine, as well as the ability to set the upload path. Internally use recursive methods to upload all the methods in the file queue to the server. Using Uploaditemprogress to notify the progress of external uploads, use uploadstatuschanged to notify file upload status to update the UI.
There are three main objects in the Uploaderapp.js, one is a simple jquery object (app$) similar to jquery. Used primarily for binding events. One is the Uploaderarea object, the window area where the drag is uploaded, and the other is the entry object Uploadermain object. is primarily used to initialize an object, providing an external Init method to initialize the entire object.
For code on app$ and Uploaderarea objects, download the source code, and simply explain the Uploadermain object below.
(function (APP) {var _self;
function Uploadermain (id) {this._id = ID;
This._area = null;
This.uploaders = [];
This._url = ' File/uploader ';
} Uploadermain.prototype = {init:function () {_self = this;
This._initarea ();
This._initqueueeng ();
}, _initqueueeng:function () {UPLOADERQUEUE.ENGINE.SETURL (This._url); uploaderQueue.Engine.uploadStatusChanged = function (key, status) {if (Status = = UploaderQueue.UploadStatus.Uploadin
g) {_self._area.hideitemcancel (key);
else if (status = = UploaderQueue.UploadStatus.Complete) {_self._area.completeitem (key);
_self._area.showitemcancel (key);
} uploaderQueue.Engine.uploadItemProgress = function (key, E) {var progress = e.position/e.total;
_self._area.changeitemprogress (Key, Math.Round (Progress * 100));
}, _initarea:function () {This._area = new App.area (this._id);
This._area.init (); This._area.drop = function (e) {var key = uploaderQueue.Queue.add ({files:e.datatransfer.files});
UploaderQueue.Engine.run ();
Return key;
} This._area.cancelitem = function (key) {uploaderQueue.Queue.remove (key);
}
}
};
App.main = Uploadermain;
}) (Window.uploaderapp);
In the Uploadermain object, the equivalent of the intermediary between the objects, mainly to do the initialization of the object function, and the object to call each other. Enables the various objects to collaborate with each other to complete the function of the entire module. Provides an Init method for initializing the entire program, with only the following code in the HTML page:
<script type= "Text/javascript" >
var main=new uploaderapp.main (' container ');
Main.init ();
</script>
The above code is to create a portal object and then use the Init method to start the entire program.
The above is the front-end JS Main method to do a simple explanation, if you want to learn more about the download source code. The following is a simple look at the backend JS (Nodejs) Implementation of the main code.
In the express basic knowledge, has been said in the Express has been the file upload function to do a complete package, when routing to the action, the file has been uploaded to a temporary directory, this temporary directory can be configured in the App.js, configured in the following way:
App.use (Express.bodyparser ({
uploaddir:__dirname+ '/public/temp '
}));
In this way after file upload file is stored in the/public/temp directory, the file name is also express through a certain algorithm randomly obtained. In the action we write we simply move the files in the temporary directory to the directory where the files are stored in the server, and then delete the files in the temp directory. The specific code is as follows:
function Uploader (req, res) {
if (req.files!= ' undifined ') {
console.dir (req.files);
Utils.mkdir (). Then (function (path) {
UploadFile (req, res, path, 0);}
);
}
function UploadFile (req, res, path, index) {
var temppath = Req.files.file[index].path;
var name = Req.files.file[index].name;
if (TempPath) {
var rename = promise.denodeify (fs.rename);
Rename (temppath, path + name). Then (function () {
var unlink = promise.denodeify (fs.unlink);
Unlink (TempPath);
}). Then (function () {
if (index = = req.files.file.length-1) {
var res = {
code:1,
des: ' Upload succeeded '
};< C22/>res.send (res);
else {
UploadFile (req, res, path, index + 1);}}}
2, realize the effect
Four, get the code
Code Download Address: http://www.jb51.net/jiaoben/202117.html