node.js解决获取图片真实文件类型的问题


Posted in Javascript onDecember 20, 2014

遇到一个需求:假定有一个图片文件,真实的类型为jpg,而有人偷懒把jpg直接复制一张,存为同名的png文件,这样在as3读取文件时不会遇到问题,但手机c++在读取文件时却遇到问题了 - -!

现在就需要写一个程序,遍历所有文件夹下的文件,查找文件格式“不正常”的文件。我们的资源主要是gif、png、jpg,最开始,我到网上找到一篇文章:根据二进制流及文件头获取文件类型mime-type,然后读取文件二进制的头信息,获取其真实的文件类型,对与通过后缀名获得的文件类型进行比较。

var fd = fs.openSync(new_file_path, 'r');

var buffer = new Buffer(8);
var mineType = mime.lookup(new_file_path);

var fileType = mime.extension(mineType);
fs.readSync(fd, buffer, 0, 8, 0);

var newBuf = buffer.slice(0, 4);

var head_1 = newBuf[0].toString(16);

var head_2 = newBuf[1].toString(16);

var head_3 = newBuf[2].toString(16);

var head_4 = newBuf[3].toString(16);

var head_iden = head_1 + head_2;
var tempFileType = FILE_TYPE_CONFIG[head_iden];

if (!tempFileType) {

    head_iden += head_3;
    tempFileType = FILE_TYPE_CONFIG[head_iden];
    if (!tempFileType) {

        var msg = "Unknow fileType " + new_file_path + '-' + fileType;

        showLog(msg);

        continue;

    }

}
if (tempFileType != fileType) {

    var msg = "Error fileType" + new_file_path + '-' + fileType + '|' + tempFileType + '--正确的图像文件格式';

    showLog(msg);
    g_errorFileTypArr.push(msg);

}

后来搜索node image相关的信息时,找到这篇文章:node.js module ranking>> (images)

然后筛选到一个模块“node-imageinfo”,写了一个例子进行测试(故意把jpg文件直接修改后缀名为png):

node.js解决获取图片真实文件类型的问题

node.js解决获取图片真实文件类型的问题

它的源码,有兴趣可以研究一下:

function readUInt32(buffer, offset, bigEndian) {

    if (buffer.readUInt32) {

        return buffer.readUInt32(offset, bigEndian);

    }
    var value;

    if (bigEndian) {

        if (buffer.readUInt32BE) {

            return buffer.readUInt32BE(offset);

        }

        value = (buffer[offset] << 24) + (buffer[offset+1] << 16) + (buffer[offset+2] << 8) + buffer[offset+3];

    }

    else {

        if (buffer.readUInt32LE) {

            return buffer.readUInt32LE(offset);

        }

        value = buffer[offset] + (buffer[offset+1] << 8) + (buffer[offset+2] << 16) + (buffer[offset+3] << 24);

    }

    return value;

}
function readUInt16(buffer, offset, bigEndian) {

    if (buffer.readUInt16) {

        return buffer.readUInt16(offset, bigEndian);

    }
    var value;

    if (bigEndian) {

        if (buffer.readUInt16BE) {

            return buffer.readUInt16BE(offset);

        }

        value = (buffer[offset] << 8) + buffer[offset+1];

    }

    else {

        if (buffer.readUInt16LE) {

            return buffer.readUInt16LE(offset);

        }

        value = buffer[offset] + (buffer[offset+1] << 8);

    }

    return value;

}
function readBit(buffer, offset, bitOffset) {

    if (bitOffset > 7) {

        offset += Math.floor(bitOffset / 8);

        bitOffset = bitOffset % 8;

    }
    var b = buffer[offset];

    if (bitOffset < 7) {

        b >>>= (7 - bitOffset);

    }
    var val = b & 0x01;

    return val;

}
function readBits(buffer, offset, bitOffset, bitLen, signed) {

    var val = 0;

    

    var neg = false;

    if (signed) {

        if (readBit(buffer, offset, bitOffset) > 0) {

            neg = true;

        }

        bitLen--;

        bitOffset++;

    }
    var bytes = [];

    for (var i = 0; i < bitLen; i++) {

        var b = readBit(buffer, offset, bitOffset + i);

        if (i>0 && (bitLen - i) % 8 == 0) {

            bytes.push(val);

            val = 0;

        }

        val <<= 1;

        val |= b;

    }

    bytes.push(val);
    val = new Buffer(bytes);

    val.negative = neg?true:false;

    return val;

}
function imageInfoPng(buffer) {

    var imageHeader = [0x49, 0x48, 0x44, 0x52],

        pos = 12;
    if (!checkSig(buffer, pos, imageHeader)) {

        return false;

    }
    pos += 4;

    return {

        type: 'image',

        format: 'PNG',

        mimeType: 'image/png',

        width: readUInt32(buffer, pos, true),

        height: readUInt32(buffer, pos+4, true),

    };

}
function imageInfoJpg(buffer) {

    var pos = 2,

        len = buffer.length,

        sizeSig = [0xff, [0xc0, 0xc2]];
    while (pos < len) {

        if (checkSig(buffer, pos, sizeSig)) {

            pos += 5;

            return {

                type: 'image',

                format: 'JPG',

                mimeType: 'image/jpeg',

                width: readUInt16(buffer, pos+2, true),

                height: readUInt16(buffer, pos, true),

            };

        }
        pos += 2;

        var size = readUInt16(buffer, pos, true);

        pos += size;

    }

}
function imageInfoGif(buffer) {

    var pos = 6;
    return {

        type: 'image',

        format: 'GIF',

        mimeType: 'image/gif',

        width: readUInt16(buffer, pos, false),

        height: readUInt16(buffer, pos+2, false),

    };

}
function imageInfoSwf(buffer) {

    var pos = 8,

        bitPos = 0,

        val;
    if (buffer[0] === 0x43) {

        try {

            // If you have zlib available ( npm install zlib ) then we can read compressed flash files

            buffer = require('zlib').inflate(buffer.slice(8, 100));

            pos = 0;

        }

        catch (ex) {

            // Can't get width/height of compressed flash files... yet (need zlib)

            return {

                type: 'flash',

                format: 'SWF',

                mimeType: 'application/x-shockwave-flash',

                width: null,

                height: null,

            }

        }

    }
    var numBits = readBits(buffer, pos, bitPos, 5)[0];

    bitPos += 5;

    

    val = readBits(buffer, pos, bitPos, numBits, true);

    var xMin = (numBits > 9 ? readUInt16(val, 0, true) : val[0]) * (val.negative ? -1 : 1);

    bitPos += numBits;
    val = readBits(buffer, pos, bitPos, numBits, true);

    var xMax = (numBits > 9 ? readUInt16(val, 0, true) : val[0]) * (val.negative ? -1 : 1);

    bitPos += numBits;
    val = readBits(buffer, pos, bitPos, numBits, true);

    var yMin = (numBits > 9 ? readUInt16(val, 0, true) : val[0]) * (val.negative ? -1 : 1);

    bitPos += numBits;
    val = readBits(buffer, pos, bitPos, numBits, true);

    var yMax = (numBits > 9 ? readUInt16(val, 0, true) : val[0]) * (val.negative ? -1 : 1);
    return {

        type: 'flash',

        format: 'SWF',

        mimeType: 'application/x-shockwave-flash',

        width: Math.ceil((xMax - xMin) / 20),

        height: Math.ceil((yMax - yMin) / 20),

    };

}
function checkSig(buffer, offset, sig) {

    var len = sig.length;

    for (var i = 0; i < len; i++) {

        var b = buffer[i+offset],

            s = sig[i],

            m = false;
        if ('number' == typeof s) {

            m = s === b;

        }

        else {

            for (var k in s) {

                var o = s[k];

                if (o === b) {

                    m = true;

                }

            }

        }
        if (!m) {

            return false;

        }

    }
    return true;

}
module.exports = function imageInfo(buffer, path) {

    var pngSig = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];

    var jpgSig = [0xff, 0xd8, 0xff];

    var gifSig = [0x47, 0x49, 0x46, 0x38, [0x37, 0x39], 0x61];

    var swfSig = [[0x46, 0x43], 0x57, 0x53];
    if (checkSig(buffer, 0, pngSig)) return imageInfoPng(buffer);

    if (checkSig(buffer, 0, jpgSig)) return imageInfoJpg(buffer);

    if (checkSig(buffer, 0, gifSig)) return imageInfoGif(buffer);

    if (checkSig(buffer, 0, swfSig)) return imageInfoSwf(buffer);
    return false;

};
Javascript 相关文章推荐
js获取图片大小的函数代码
Sep 20 Javascript
js调用图片隐藏&amp;显示实现代码
Sep 13 Javascript
JS实现点击链接取消跳转效果的方法
Jan 24 Javascript
jQuery操作元素css样式的三种方法
Jun 04 Javascript
javascript中attribute和property的区别详解
Jun 05 Javascript
jquery.validate 自定义验证方法及validate相关参数
Jan 18 Javascript
Angular设置title信息解决SEO方面存在问题
Aug 19 Javascript
vue加载完成后的回调函数方法
Sep 07 Javascript
了解JavaScript中的选择器
May 24 Javascript
vue.js循环radio的实例
Nov 07 Javascript
vue路由守卫,限制前端页面访问权限的例子
Nov 11 Javascript
解决iView Table组件宽度只变大不变小的问题
Nov 13 Javascript
javascript使用for循环批量注册的事件不能正确获取索引值的解决方法
Dec 20 #Javascript
Node.js实现批量去除BOM文件头
Dec 20 #Javascript
javascript删除一个html元素节点的方法
Dec 20 #Javascript
Node.js中调用mysql存储过程示例
Dec 20 #Javascript
零基础搭建Node.js、Express、Ejs、Mongodb服务器及应用开发入门
Dec 20 #Javascript
jQuery多媒体插件jQuery Media Plugin使用详解
Dec 19 #Javascript
jquery图片播放浏览插件prettyPhoto使用详解
Dec 19 #Javascript
You might like
德劲1107的电路分析与打磨
2021/03/02 无线电
单点登录 Ucenter示例分析
2013/10/29 PHP
win7 wamp 64位 php环境开启curl服务遇到的问题及解决方法
2018/09/16 PHP
关于Laravel-admin的基础用法总结和自定义model详解
2019/10/08 PHP
php设计模式之原型模式分析【星际争霸游戏案例】
2020/03/23 PHP
for 循环性能比较 提高for循环的效率
2009/03/19 Javascript
javascript 变量作用域 代码分析
2009/06/26 Javascript
javascript 设置文本框中焦点的位置
2009/11/20 Javascript
修复IE9&amp;safari 的sort方法
2011/10/21 Javascript
js由下向上不断上升冒气泡效果实例
2015/05/07 Javascript
JavaScript中setFullYear()方法的使用详解
2015/06/11 Javascript
基于javascript实现tab切换特效
2016/03/29 Javascript
JS动态的把左边列表添加到右边的实现代码(可上下移动)
2016/11/17 Javascript
angular+ionic 的app上拉加载更新数据实现方法
2017/01/16 Javascript
JS简单实现获取元素的封装操作示例
2017/04/07 Javascript
js 显示日期时间的实例(时间过一秒加1)
2017/10/25 Javascript
浅谈vue-router 路由传参的方法
2017/12/27 Javascript
layui当点击文本框时弹出选择框,显示选择内容的例子
2019/09/02 Javascript
JavaScript 事件代理需要注意的地方
2020/09/08 Javascript
Python ORM框架SQLAlchemy学习笔记之数据查询实例
2014/06/10 Python
python实现在无须过多援引的情况下创建字典的方法
2014/09/25 Python
浅析使用Python操作文件
2017/07/31 Python
python中requests和https使用简单示例
2018/01/18 Python
在python中pandas读文件,有中文字符的方法
2018/12/12 Python
Python中文件的写入读取以及附加文字方法
2019/01/23 Python
python+numpy实现的基本矩阵操作示例
2019/07/19 Python
django foreignkey外键使用的例子 相当于left join
2019/08/06 Python
html5使用canvas绘制一张图片
2014/12/15 HTML / CSS
全球地下的服装和态度:Slam Jam
2018/02/04 全球购物
Ray-Ban雷朋西班牙官网:全球领先的太阳眼镜品牌
2018/11/28 全球购物
大学生活自我评价
2014/04/09 职场文书
三八妇女节活动总结
2014/05/04 职场文书
大学生求职信范文
2014/05/24 职场文书
生日宴会策划方案
2014/06/03 职场文书
公司文体活动总结
2015/05/07 职场文书
2015年学校保卫部工作总结
2015/05/11 职场文书