NodeJs獲取文件的MD5

本文是介紹通過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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蒂培,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌翎冲,老刑警劉巖媳荒,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钳枕,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡鱼炒,警方通過查閱死者的電腦和手機(jī)田柔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)欣舵,“玉大人缀磕,你說我怎么就攤上這事⊥嗖希” “怎么了牲剃?”我有些...
    開封第一講書人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)缠犀。 經(jīng)常有香客問我聪舒,道長(zhǎng),這世上最難降的妖魔是什么箱残? 我笑而不...
    開封第一講書人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮敬惦,結(jié)果婚禮上间涵,老公的妹妹穿的比我還像新娘。我一直安慰自己勾哩,他們只是感情好思劳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開白布妨猩。 她就那樣靜靜地躺著,像睡著了一般威兜。 火紅的嫁衣襯著肌膚如雪庐椒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,554評(píng)論 1 305
  • 那天笔宿,我揣著相機(jī)與錄音棱诱,去河邊找鬼。 笑死炬灭,一個(gè)胖子當(dāng)著我的面吹牛靡菇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播镰官,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼泳唠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了拓哺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤闲孤,失蹤者是張志新(化名)和其女友劉穎烤礁,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體脚仔,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年们颜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了猎醇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡阻问,死狀恐怖音半,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情煌茬,我是刑警寧澤彻桃,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布邻眷,位于F島的核電站,受9級(jí)特大地震影響肆饶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜葫督,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望偎快。 院中可真熱鬧洽胶,春花似錦、人聲如沸丐怯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至些膨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肢预,已是汗流浹背洼哎。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留锭沟,地道東北人识补。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像祝辣,于是被迫代替她去往敵國(guó)和親切油。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,133評(píng)論 25 707
  • Node.js是目前非趁漯模火熱的技術(shù)岛琼,但是它的誕生經(jīng)歷卻很奇特。 眾所周知槐瑞,在Netscape設(shè)計(jì)出JavaScri...
    w_zhuan閱讀 3,615評(píng)論 2 41
  • 前兩部分我們已經(jīng)完成了博客頁(yè)面的展示和后臺(tái)頁(yè)面的展示: React技術(shù)棧+Express+Mongodb實(shí)現(xiàn)個(gè)人博...
    SamDing閱讀 5,465評(píng)論 1 12
  • 中午祠挫,我做了土雞燉山藥悼沿,跟遙哥共進(jìn)午餐。 我剛挑了一塊帶骨的雞肉糟趾,用筷子夾著啃。遙哥在旁邊冷不丁冒了一句:“媽媽蝶柿,...
    思小圓閱讀 901評(píng)論 5 6
  • 早在父親節(jié)那天就想寫這篇文章非驮,但那天微信全都在為“父愛如山”刷屏,我若反其道而行之芙扎,指定是挨罵的節(jié)奏填大,呵呵! 上...
    夢(mèng)逢桃源閱讀 295評(píng)論 0 0