本文是介紹通過NodeJs的服務(wù)器根时,前臺(tái)上傳采用jquery的fileupload,后臺(tái)是express框架的后臺(tái)确虱,話不多說替裆,上代碼
首先是HTML文件
<script src="upload/jquery-1.8.2.min.js"></script>
<script src="upload/jquery.ui.widget.js"></script>
<script src="upload/jquery.iframe-transport.js"></script>
<script src="upload/jquery.fileupload.js"></script>
<script src="upload/upload.js"></script>
在html中加入以下依賴辆童,前面的不用多說,最后一個(gè)如下
$(function() {
$('#fileupload').fileupload({
url: '/upload',
dataType: 'json',
//autoUpload: false,
//acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
maxFileSize: 5000000, // 5 MB
// Enable image resizing, except for Android and Opera,
// which actually support image resizing, but fail to
// send Blob objects via XHR requests:
disableImageResize: /Android(?!.*Chrome)|Opera/
.test(window.navigator.userAgent),
previewMaxWidth: 100,
previewMaxHeight: 100,
previewCrop: true
}).on('fileuploadadd', function (e, data) {
var arr1=data.files[0].name.lastIndexOf(".");
var arr2=data.files[0].name.length;
var suffix=data.files[0].name.substring(arr1+1,arr2)
var code = data.files[0].name.split('_')
var versionName = parseInt(code[1]);
var versionCode = parseInt(code[2].split('.')[0]);
console.log(versionName);
console.log(versionCode);
var nowVersionName = parseInt($('#versionName').html());
var nowVersionCode = parseInt($('#versionCode').html());
if( versionName < nowVersionName){
alert('版本名稱低于當(dāng)前版本故黑,請(qǐng)確認(rèn)后上傳');
return false;
}
if( versionName > nowVersionName &&(versionCode != 1)){
alert('版本號(hào)有誤场晶,請(qǐng)確認(rèn)后更新');
return false;
}
if(versionName == nowVersionName && ((versionCode - nowVersionCode) != 1)){
alert('版本號(hào)有誤怠缸,請(qǐng)確認(rèn)后更新');
return false;
}
if(suffix != 'apatch'){
alert('請(qǐng)確認(rèn)補(bǔ)丁格式是否正確');
return false;
}else{
$('#progress').show();
}
//data.context = $('<div/>').appendTo('#files');
/* $.each(data.files, function (index, file) {
var node = $('<div class="alert alert-success"/>')
.append($('<span/>').text('文件: ' + file.name + ' 已經(jīng)加載成功'));
//if (!index) {
// node
// .append('<br>')
// .append(uploadButton.clone(true).data(data));
//}
node.appendTo(data.context);
});*/
}).on('fileuploadprocessalways', function (e, data) {
var index = data.index,
file = data.files[index],
node = $(data.context.children()[index]);
if (file.preview) {
node
.prepend('<br>')
.prepend(file.preview);
}
if (file.error) {
node
.append('<br>')
.append($('<span class="text-danger"/>').text(file.error));
}
if (index + 1 === data.files.length) {
data.context.find('button')
.text('Upload')
.prop('disabled', !!data.files.error);
}
}).on('fileuploadprogressall', function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .progress-bar').css(
'width',
progress + '%'
);
}).on('fileuploaddone', function (e, data) {
$.each(data.result.files, function (index, file) {
if (file.url) {
var link = $('<a>')
.attr('target', '_blank')
.prop('href', file.url);
$(data.context.children()[index])
.wrap(link);
} else if (file.error) {
var error = $('<span class="text-danger"/>').text(file.error);
$(data.context.children()[index])
.append('<br>')
.append(error);
}
$('.transMedia').attr('id',file);
$('#progress').hide();
$('#files').show();
});
location.reload();
}).on('fileuploadfail', function (e, data) {
$.each(data.files, function (index, file) {
var error = $('<span class="text-danger"/>').text('File upload failed.');
$(data.context.children()[index])
.append('<br>')
.append(error);
});
}).prop('disabled', !$.support.fileInput)
.parent().addClass($.support.fileInput ? undefined : 'disabled');
});
在以上文件中有一段代碼大家不用在意扳炬,是我為了判斷上傳文件的版本號(hào)是否正確等做了一些判斷搔体,主要在on('fileuploadadd')中
var arr1=data.files[0].name.lastIndexOf(".");
var arr2=data.files[0].name.length;
var suffix=data.files[0].name.substring(arr1+1,arr2)
var code = data.files[0].name.split('_')
var versionName = parseInt(code[1]);
var versionCode = parseInt(code[2].split('.')[0]);
console.log(versionName);
console.log(versionCode);
var nowVersionName = parseInt($('#versionName').html());
var nowVersionCode = parseInt($('#versionCode').html());
if( versionName < nowVersionName){
alert('版本名稱低于當(dāng)前版本疚俱,請(qǐng)確認(rèn)后上傳');
return false;
}
if( versionName > nowVersionName &&(versionCode != 1)){
alert('版本號(hào)有誤,請(qǐng)確認(rèn)后更新');
return false;
}
if(versionName == nowVersionName && ((versionCode - nowVersionCode) != 1)){
alert('版本號(hào)有誤夯尽,請(qǐng)確認(rèn)后更新');
return false;
}
if(suffix != 'apatch'){
alert('請(qǐng)確認(rèn)補(bǔ)丁格式是否正確');
return false;
}else{
$('#progress').show();
}
這段代碼大家可以直接寫成
$('#progress').show();
下面直接上后臺(tái)代碼
在你的node路由中應(yīng)該存在如下代碼:
var express = require('express');
var router = express.Router();
var User = require('./controller');
router.post('/upload',User.upload);
在你的controller文件中
/**
* 前端上傳文件到服務(wù)器
* @param req
* @param res
*/
exports.upload = (req, res) => {
//versionCollection是數(shù)據(jù)庫(kù)骨架 讀取到的是version
let versionCollection = global.dbHandle.getModel('version');
//創(chuàng)建formidable對(duì)象
let form = new formidable.IncomingForm(),files=[],fields=[],docs=[];
let date = new Date();
let ms = Date.parse(date)/1000;
form.uploadDir = 'tmp/';
form.on('field', (field, value) =>{
fields.push([field, value]);
}).on('file', function(field, file) {
docs.push(file);
//文件重命名
fs.renameSync(file.path, "tmp/" + ms + file.name);
}).on('end', () => {
//文件上傳結(jié)束
res.writeHead(200, {'content-type': 'text/plain'});
let out = { Resopnse:{ 'result-code':0, timeStamp:new Date(),},
files:docs
};
let sout=JSON.stringify(out);
res.end(sout);
});
form.parse(req, function(err, fields, files) {
//當(dāng)文件上傳結(jié)束后開始讀取文件的md5 size 等數(shù)據(jù)
err && console.log('formidabel error : ' + err);
/**
* 讀取到文件
*/
let file = files['files[]'];
let fileLocalUrl = express.pkgUrl + ms + file.name;
let downloadUrl = express.downloadUrl + ms + file.name;
let fileName = file.name.split('_');
let pkgInfo = {};
pkgInfo.name = fileName[0];
pkgInfo.versionName = fileName[1];
pkgInfo.versionCode = fileName[2].split('.')[0];
pkgInfo.size = file.size;
pkgInfo.url = downloadUrl;
pkgInfo.lastModified = getNowFormatDate();
/**
* 創(chuàng)建文件流獲取md5碼
*/
readFileMd5(fileLocalUrl).then((md5String) => {
pkgInfo.md5 = md5String;
findCurrentVersion().then((version) =>{
if(version.err){
console.log('err: ' + version.err)
return;
}
if(version.msg && version.msg == 'empty'){
versionCollection.create(pkgInfo,(err)=>{
if(err){
console.log('DB FAILED');
return;
}
console.log('創(chuàng)建數(shù)據(jù)庫(kù)成功成功');
return;
})
}else{
pkgInfo._id = version._id;
version = pkgInfo;
versionCollection.update(version,(err)=>{
if(err){
console.log('DB FAILED');
return;
}
console.log('更新數(shù)據(jù)庫(kù)成功成功');
return;
})
}
})
})
});
};
上面的代碼可讀性還是很高的,用了一些ES6的語(yǔ)法陈轿,我用的是node@6.10.2 對(duì)ES6的支持達(dá)到了90%
其中調(diào)用了一個(gè)readFileMd5的方法 麦射,方法如下
let readFileMd5 = (url) =>{
return new Promise((reslove) => {
let md5sum = crypto.createHash('md5');
let stream = fs.createReadStream(url);
stream.on('data', function(chunk) {
md5sum.update(chunk);
});
stream.on('end', function() {
let fileMd5 = md5sum.digest('hex');
reslove(fileMd5);
})
})
}
當(dāng)然在你的文件中需要引入crypto,通過crypto創(chuàng)建hash蛔琅,然后通過fs.createReadStream 讀取到文件的地址峻呛,然后通過stream的兩個(gè)方法最后reslove讀取好的md5,直接也用過其他同步的方式寨躁,發(fā)現(xiàn)讀取一個(gè)大文件牙勘,如一個(gè)1.5G的視頻文件就不行了,這種方法可以讀取一個(gè)大文件并且沒有產(chǎn)生異常方面。
本文只是大概講了一下整個(gè)流程,如有小伙伴需要代碼最筒,后期我會(huì)在github中把代碼貼出來(lái)蔚叨,現(xiàn)在前端沒有用到react,我正在改成react的前端邢锯,最后寫好了會(huì)放出來(lái)搀别,現(xiàn)在需要代碼可以聯(lián)系我的郵箱huang93223@126.com