视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
node.js解决获取图片真实文件类型的问题_node.js
2020-11-27 21:30:41 责编:小采
文档
遇到一个需求:假定有一个图片文件,真实的类型为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 = [0x, 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;
};

下载本文
显示全文
专题