NodeJs获取文件的MD5

本文是介绍通过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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,802评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,109评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,683评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,458评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,452评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,505评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,901评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,550评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,763评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,556评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,629评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,330评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,898评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,897评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,140评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,807评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,339评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,373评论 25 707
  • Node.js是目前非常火热的技术,但是它的诞生经历却很奇特。 众所周知,在Netscape设计出JavaScri...
    w_zhuan阅读 3,606评论 2 41
  • 前两部分我们已经完成了博客页面的展示和后台页面的展示: React技术栈+Express+Mongodb实现个人博...
    SamDing阅读 5,448评论 1 12
  • 中午,我做了土鸡炖山药,跟遥哥共进午餐。 我刚挑了一块带骨的鸡肉,用筷子夹着啃。遥哥在旁边冷不丁冒了一句:“妈妈,...
    思小圆阅读 894评论 5 6
  • 早在父亲节那天就想写这篇文章,但那天微信全都在为“父爱如山”刷屏,我若反其道而行之,指定是挨骂的节奏,呵呵! 上...
    梦逢桃源阅读 291评论 0 0