NodeJs获取文件的MD5
2017-05-30 本文已影响0人
Tangpriest
本文是介绍通过NodeJs的服务器,前台上传采用jquery的fileupload,后台是express框架的后台,话不多说,上代码
首先是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中加入以下依赖,前面的不用多说,最后一个如下
$(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('版本名称低于当前版本,请确认后上传');
return false;
}
if( versionName > nowVersionName &&(versionCode != 1)){
alert('版本号有误,请确认后更新');
return false;
}
if(versionName == nowVersionName && ((versionCode - nowVersionCode) != 1)){
alert('版本号有误,请确认后更新');
return false;
}
if(suffix != 'apatch'){
alert('请确认补丁格式是否正确');
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 + ' 已经加载成功'));
//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');
});
在以上文件中有一段代码大家不用在意,是我为了判断上传文件的版本号是否正确等做了一些判断,主要在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('版本名称低于当前版本,请确认后上传');
return false;
}
if( versionName > nowVersionName &&(versionCode != 1)){
alert('版本号有误,请确认后更新');
return false;
}
if(versionName == nowVersionName && ((versionCode - nowVersionCode) != 1)){
alert('版本号有误,请确认后更新');
return false;
}
if(suffix != 'apatch'){
alert('请确认补丁格式是否正确');
return false;
}else{
$('#progress').show();
}
这段代码大家可以直接写成
$('#progress').show();
下面直接上后台代码
在你的node路由中应该存在如下代码:
var express = require('express');
var router = express.Router();
var User = require('./controller');
router.post('/upload',User.upload);
在你的controller文件中
/**
* 前端上传文件到服务器
* @param req
* @param res
*/
exports.upload = (req, res) => {
//versionCollection是数据库骨架 读取到的是version
let versionCollection = global.dbHandle.getModel('version');
//创建formidable对象
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', () => {
//文件上传结束
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) {
//当文件上传结束后开始读取文件的md5 size 等数据
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();
/**
* 创建文件流获取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('创建数据库成功成功');
return;
})
}else{
pkgInfo._id = version._id;
version = pkgInfo;
versionCollection.update(version,(err)=>{
if(err){
console.log('DB FAILED');
return;
}
console.log('更新数据库成功成功');
return;
})
}
})
})
});
};
上面的代码可读性还是很高的,用了一些ES6的语法,我用的是node@6.10.2 对ES6的支持达到了90%
其中调用了一个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);
})
})
}
当然在你的文件中需要引入crypto,通过crypto创建hash,然后通过fs.createReadStream 读取到文件的地址,然后通过stream的两个方法最后reslove读取好的md5,直接也用过其他同步的方式,发现读取一个大文件,如一个1.5G的视频文件就不行了,这种方法可以读取一个大文件并且没有产生异常。
本文只是大概讲了一下整个流程,如有小伙伴需要代码,后期我会在github中把代码贴出来,现在前端没有用到react,我正在改成react的前端,最后写好了会放出来,现在需要代码可以联系我的邮箱huang93223@126.com