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资料toString 方法
Mar 13 Javascript
jQuery中的.bind()、.live()和.delegate()之间区别分析
Jun 08 Javascript
Extjs中的GridPanel隐藏列会显示在menuDisabled中解决方法
Jan 27 Javascript
jquery中常用的函数和属性详细解析
Mar 07 Javascript
Javascript基础知识(一)核心基础语法与事件模型
Sep 29 Javascript
jQuery中is()方法用法实例
Jan 06 Javascript
用JavaScript显示浏览器客户端信息的超相近教程
Jun 18 Javascript
javascript insertAfter()定义与用法示例
Jul 25 Javascript
JavaScript实现简单的文本逐字打印效果示例
Apr 12 Javascript
Vue中图片Src使用变量的方法
Oct 30 Javascript
jquery实现点击弹出对话框
Feb 08 jQuery
微信小程序实现音乐播放页面布局
Dec 11 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
一个更简单的无限级分类菜单代码
2007/01/16 PHP
基于php的微信公众平台开发入门实例
2015/04/15 PHP
Thinkphp实现短信验证注册功能
2016/10/18 PHP
2020最新版 PhpStudy V8.1版本下载安装使用详解
2020/10/30 PHP
js 强制弹出窗口代码研究-又一款代码
2010/03/20 Javascript
JQuery为textarea添加maxlength属性的代码
2010/04/07 Javascript
jquery获取元素值的方法(常见的表单元素)
2013/11/15 Javascript
javascript实现的多个层切换效果通用函数实例
2015/07/06 Javascript
JavaScript基础篇(6)之函数表达式闭包
2015/12/11 Javascript
客户端验证用户名和密码的方法详解
2016/06/16 Javascript
AngularJS 表达式详细讲解及实例代码
2016/07/26 Javascript
WEB 前端开发中防治重复提交的实现方法
2016/10/26 Javascript
canvas雪花效果核心代码分享
2017/02/19 Javascript
js实现简单选项卡功能
2020/03/23 Javascript
Vue项目中使用better-scroll实现菜单映射功能方法
2019/09/11 Javascript
Js图片点击切换轮播实现代码
2020/07/27 Javascript
[46:58]完美世界DOTA2联赛PWL S3 Forest vs LBZS 第一场 12.17
2020/12/19 DOTA
使用Python求解最大公约数的实现方法
2015/08/20 Python
实例讲解Python设计模式编程之工厂方法模式的使用
2016/03/02 Python
python去除文件中空格、Tab及回车的方法
2016/04/12 Python
python线程、进程和协程详解
2016/07/19 Python
Python爬虫之xlml解析库(全面了解)
2017/08/08 Python
使用python读取txt文件的内容,并删除重复的行数方法
2018/04/18 Python
tensorflow 中对数组元素的操作方法
2018/07/27 Python
Python访问MongoDB,并且转换成Dataframe的方法
2018/10/15 Python
python生成lmdb格式的文件实例
2018/11/08 Python
Python开发之Nginx+uWSGI+virtualenv多项目部署教程
2019/05/13 Python
通过实例解析Python调用json模块
2019/12/11 Python
Python简单实现区域生长方式
2020/01/16 Python
pytorch实现MNIST手写体识别
2020/02/14 Python
高级方案规划工程师岗位职责
2013/11/29 职场文书
企业承诺书格式
2014/05/21 职场文书
2014党员民主评议个人思想剖析发言
2014/09/19 职场文书
阿凡达观后感
2015/06/10 职场文书
庆元旦主持词
2015/07/06 职场文书
云服务器部署 Web 项目的实现步骤
2022/06/28 Servers