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创建优美的页面滑动块效果 - Glider.js
Sep 27 Javascript
两个JavaScript jsFiddle JSBin在线调试器
Mar 14 Javascript
解决IE下select标签innerHTML插入option的BUG(兼容IE,FF,Opera,Chrome,Safari)
May 13 Javascript
js Array对象的扩展函数代码
Apr 24 Javascript
利用了jquery的ajax实现二级联互动菜单
Dec 02 Javascript
js实现DOM走马灯特效的方法
Jan 21 Javascript
JavaScript中的值是按值传递还是按引用传递问题探讨
Jan 30 Javascript
基于jquery实现鼠标左右拖动滑块滑动附源码下载
Dec 23 Javascript
jQuery的事件预绑定
Dec 05 Javascript
Angular2关于@angular/cli默认端口号配置的问题
Jul 15 Javascript
详谈DOM简介及节点、属性、查找节点的方法
Nov 16 Javascript
element-ui table组件如何使用render属性的实现
Nov 04 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
PHP编程函数安全篇
2013/01/08 PHP
PHP的MVC模式实现原理分析(一相简单的MVC框架范例)
2014/04/29 PHP
清除网页历史记录,屏蔽后退按钮!
2008/12/22 Javascript
Javascript绝句欣赏 一些经典的js代码
2012/02/22 Javascript
Js中setTimeout()和setInterval() 何时被调用执行的用法
2013/04/12 Javascript
使用js对select动态添加和删除OPTION示例代码
2013/08/12 Javascript
解决css和js的{}与smarty定界符冲突问题的两种方法
2013/09/10 Javascript
动态创建script在IE中缓存js文件时导致编码的解决方法
2014/05/04 Javascript
javascipt:filter过滤介绍及使用
2014/09/10 Javascript
nodejs通过phantomjs实现下载网页
2015/05/04 NodeJs
js/jq仿window文件夹移动/剪切/复制等操作代码
2017/03/08 Javascript
axios向后台传递数组作为参数的方法
2018/08/11 Javascript
React SSR样式及SEO的实践
2018/10/22 Javascript
Vue列表渲染的示例代码
2018/11/01 Javascript
TypeScript开发Node.js程序的方法
2019/04/30 Javascript
基于jquery实现的tab选项卡功能示例【附源码下载】
2019/06/10 jQuery
layui 选择列表,打勾,点击确定返回数据的例子
2019/09/02 Javascript
支付宝小程序实现省市区三级联动
2020/06/21 Javascript
JavaScript中作用域链的概念及用途讲解
2020/08/06 Javascript
通过实例解析JavaScript常用排序算法
2020/09/02 Javascript
Python while、for、生成器、列表推导等语句的执行效率测试
2015/06/03 Python
python3.5 + PyQt5 +Eric6 实现的一个计算器代码
2017/03/11 Python
Python实现的爬取网易动态评论操作示例
2018/06/06 Python
Python计算开方、立方、圆周率,精确到小数点后任意位的方法
2018/07/17 Python
Python实现简单层次聚类算法以及可视化
2019/03/18 Python
pycharm实现print输出保存到txt文件
2020/06/01 Python
基于css3实现漂亮便签样式
2013/03/18 HTML / CSS
意大利在线购买隐形眼镜网站:VisionDirect.it
2019/03/18 全球购物
PHP面试题集
2016/12/18 面试题
网上书店创业计划书
2014/01/12 职场文书
行政工作个人的自我评价
2014/02/13 职场文书
《陶罐和铁罐》教学反思
2014/02/19 职场文书
关于青春的演讲稿
2014/05/05 职场文书
2014年控辍保学工作总结
2014/12/08 职场文书
学校教师培训工作总结
2015/10/14 职场文书
opencv深入浅出了解机器学习和深度学习
2022/03/17 Python