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

遇到一个需求:假定有一个图片文件,真实的类型为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):

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

代码如下:

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;
};

(0)

相关推荐

  • node.js开机自启动脚本文件

    复制代码 代码如下: #!/bin/bash ### BEGIN INIT INFO # Provides:       xiyoulib # Required-Start:   $all # Required-Stop:     $all # Default-Start:     2 3 4 5 # Default-Stop:   0 1 6 # Short-Description: Start daemon at boot time # Description:     Enable ser

  • Node.js实现文件上传

    在工作中碰到了这样的需求,需要用nodejs 来上传文件,之前也只是知道怎么通过浏览器来上传文件, 用nodejs的话, 相当于模拟浏览器的行为. google 了一番之后, 明白了浏览器无非就是利用http协议来给服务器传输数据, 具体协议就是<RFC 1867 - Form-based File Upload in HTML>, 在浏览器上通过form 表单来上传文件就是通过这个协议,我们可以先看看浏览器给服务端发送了什么数据, 就可以依葫芦画瓢的把上传功能实现出来.说起form 表单上传

  • Node.js文件操作详解

    Node有一组数据流API,可以像处理网络流那样处理文件,用起来很方便,但是它只允许顺序处理文件,不能随机读写文件.因此,需要使用一些更底层的文件系统操作. 本章覆盖了文件处理的基础知识,包括如何打开文件,读取文件某一部分,写数据,以及关闭文件. Node的很多文件API几乎是UNIX(POSIX)中对应文件API 的翻版,比如使用文件描述符的方式,就像UNIX里一样,文件描述符在Node里也是一个整型数字,代表一个实体在进程文件描述符表里的索引. 有3个特殊的文件描述符--1,2和3.他们分别

  • Node.js本地文件操作之文件拷贝与目录遍历的方法

    文件拷贝 NodeJS 提供了基本的文件操作 API,但是像文件拷贝这种高级功能就没有提供,因此我们先拿文件拷贝程序练手.与 copy 命令类似,我们的程序需要能接受源文件路径与目标文件路径两个参数. 小文件拷贝 我们使用 NodeJS 内置的 fs 模块简单实现这个程序如下. var fs = require('fs'); function copy(src, dst) { fs.writeFileSync(dst, fs.readFileSync(src)); } function main

  • node.js开发中使用Node Supervisor实现监测文件修改并自动重启应用

    在开发或调试Node.js应用程序的时候,当你修改js文件后,总是要按下CTRL+C终止程序,然后再重新启动,即使是修改一点小小的参数,也总是要不断地重复这几个很烦人的操作.有没有办法做到当文件修改之后,Node.js自动重新启动(或重新加载文件)以节省时间呢?一开始我是想到用grunt的watch模块来监控文件变化,但后来在网上一查,原来我们想到的,别人早已想到,并且已经做得很好.Node Supervisor正是这样一个可以实现这种需求的Node.js模块. 根据Github上的说明,Nod

  • 在Node.js中使用HTTP上传文件的方法

    开发环境 我们将使用 Visual Studio Express 2013 for Web 作为开发环境, 不过它还不能被用来做 Node.js 开发.为此我们需要安装 Node.js Tools for Visual Studio.  装好后 Visual Studio Express 2013 for Web 就会转变成一个 Node.js IDE 环境,提供创建这个应用所需要的所有东西..而基于这里提供的指导,我们需要: 下载安装 Node.js  Windows 版,选择适用你系统平台的

  • Node.JS文件系统解析实例详解

    1.Node.js 文件系统 var fs = require("fs") 2.异步和同步 读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync(). var fs = require('fs') fs.readFile( 'a.txt','utf-8', function (err,data) { if( err ) { console.error(err) }else{ console.log( "not aynsc===>

  • node.js实现逐行读取文件内容的代码

    在此之前先介绍一个逐行读取文件内容NPM:https://github.com/nickewing/line-reader,需要的朋友可以看看. 直接上代码: function readLines(input, func) { var remaining = ''; input.on('data', function(data) { remaining += data; var index = remaining.indexOf('\n'); while (index > -1) { var l

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

    遇到一个需求:假定有一个图片文件,真实的类型为jpg,而有人偷懒把jpg直接复制一张,存为同名的png文件,这样在as3读取文件时不会遇到问题,但手机c++在读取文件时却遇到问题了 - -! 现在就需要写一个程序,遍历所有文件夹下的文件,查找文件格式"不正常"的文件.我们的资源主要是gif.png.jpg,最开始,我到网上找到一篇文章:根据二进制流及文件头获取文件类型mime-type,然后读取文件二进制的头信息,获取其真实的文件类型,对与通过后缀名获得的文件类型进行比较. 复制代码

  • js和jquery如何获取图片真实的宽度和高度

    1.什么时候需要获取图片真实的宽度和高度 在做pc网页的时候,有时候会考虑按照插入的图片的尺寸来判断图片是横图还是竖图.然后判断过后给予不同的展示方式! 另外一种就是在手机页面上,在新闻页插入的图片往往都是按照图片的原尺寸来展示,如果手机屏幕太小,太大的图就会超出去!这时候有两种解决办法 1)给所有的图片加上这样的样式 1 复制代码 代码如下: .news img{margin:5px auto; display:block;width:100%; height:auto;} 但是这种方式有另外

  • angular.js+node.js实现下载图片处理详解

    前言 本文主要介绍的是angular.js+node.js实现下载图片处理,下载有两种方式,下面话不多说,来看看详细的介绍吧. 第一种: 不指定完整路径,然后发送get给server让server自己去拼接路径,然后用express的res.download来做下载: Express: var filePath = path.join(savePath, file[0].name); console.log('Download file: ' + filePath); res.download(

  • Node.js批量给图片加水印的方法

    一.准备工作: 首先,你要阅读完这篇文章:http://www.jb51.net/article/97391.htm. 然后,我们安装node.js的一个模块:imageinfo. npm install imageinfo 二.直接上DEMO: 步骤如下: step1:文件夹结构 step2:JS代码 //引用文件系统模块 var fs = require("fs"); //引用imageinfo模块 var imageInfo = require("imageinfo&q

  • Node.js 在本地生成日志文件的方法

    平常都使用console来打印 node 脚本执行时需要看到的信息,但这些信息也就只能在控制台查看.假如你希望将打印的信息输出到日志(log)文件查看的话,那就往下看看吧. 1.前言 期望: 每次运行脚本时,生成log日志存储到本地 每次执行脚本,之前日志内容清空 需要了解的知识点: fs new console.Console 2.什么是 fs 使用 node.js 对日志进行存储,就一定会对本地文件的增删改查,那么我们需要用到fs. 如果你写过 node,想必你应该见过它fs,fs全称为文件

  • 使用Node.js实现base64和png文件相互转换的方法

    前天浏览技术博客,看到大厂面试题型中有使用nodejs实现base64和图片文件相互转换的例子,刚好近期要开发这个功能,暂时记录下来,下周开发完成再做一个补充. 1. 将base64 转换为图片文件,这里举例用的png文件 const fs = require('fs'); const path = 'xxx/'+ Date.now() +'.png'; const base64 = data.replace(/^data:image\/\w+;base64,/,""); //去掉图片

  • node.js使用express-fileupload中间件实现文件上传

    目录 初始化项目 编写服务器 初始化客户端 编写组件 FileUpload Message.js Progress.js 测试 本文使用express作为服务端,使用express-fileupload库提供的中间件函数来接受从客户端传来的图片,并将图片作为文件存储在服务端.客户端使用create-react-app框架,bootstrap UI,axios发送http请求和提供进度条当前进度的值,上传成功后,根据图片在服务端上的位置,并显示图片. 初始化项目 mkdir react-file-

  • node.js使用express框架进行文件上传详解

    关于node.js使用express框架进行文件上传,主要来自于最近对Settings-Sync插件做的研究. 目前的研究算是取得的比较好的进展. Settings-Sync中通过快捷键上传文件,其实主要还是请求后端接口. 于是我便使用node.js模拟一个服务,这个服务其实就相当于github api(Settings-Sync实际请求的接口,比如token验证,gist存储创建等都是来自github 对应的api). 话不多说,直接代码贴起讲解: 1.创建一个node.js项目(这里我以ex

  • 如何使用Node.js判断png图片是否存在透明像素

    背景 png格式的图片存储空间会比jpg格式的图片大,但是png图片的质量明显更好.有时候并不需要图片的质量非常的好,但是为了减少包体,需要做一些优化,比如压缩图片,把没有带透明像素的png图片转化成jpg格式的图片.这片文章主要来讲讲怎么利用Node.js来检测没有带透明像素的png图片,以及如何把它转化成jpg图片. 代码 直接上代码 import canvas from 'canvas'; import fs from 'fs'; /** * 判断png图片是否存在透明像素 * * @pa

  • node.js解决客户端请求数据里面中文乱码的事件方法

    node.js解决客户端请求数据里面中文乱码的事件 例如代码: var http = require('http'); var server = http.createServer(); server.on('request',function(req,res){ // res.end("hello world"); res.end("你好 世界"); }); server.listen(3000,function(){ console.log("Serv

随机推荐