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

上一篇下一篇

猜你喜欢

热点阅读