首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何检测一个文件是PDF还是TIFF?

如何检测一个文件是PDF还是TIFF?
EN

Stack Overflow用户
提问于 2010-04-29 01:50:59
回答 8查看 23K关注 0票数 18

请容忍我,因为我在不知道所有背景的情况下被扔进了这个项目的中间。如果你有任何问题,相信我,我也有。

场景是这样的:我有一堆文件驻留在IIS服务器上。它们上面没有文件扩展名。只是像"asda-2342-sd3rs-asd24-ut57“之类的裸文件。没有什么直观的东西。

问题是我需要在ASP.NET (2.0)页面上提供文件,并将tiff文件显示为tiff,将PDF文件显示为PDF。不幸的是,我不知道哪一个是哪一个,我需要能够以它们各自的格式适当地显示它们。

例如,假设我需要显示两个文件,一个是tiff文件,一个是PDF文件。页面应该显示一个tiff图像,也许还有一个在新选项卡/窗口中打开PDF的链接。

问题是:

由于这些文件都是无扩展名的,我不得不强制

将所有内容都作为TIFF提供服务。但如果我这样做,PDF文件将不会显示。对于未知的文件扩展名,我可以更改IIS以强制MIME类型为PDF,但我会遇到相反的问题。

http://support.microsoft.com/kb/326965

这个问题是比我想象的简单,还是像我预期的那样糟糕?

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2010-04-29 02:20:35

好了,有足够多的人搞错了,所以我要发布一些代码来识别TIFF:

private const int kTiffTagLength = 12;
private const int kHeaderSize = 2;
private const int kMinimumTiffSize = 8;
private const byte kIntelMark = 0x49;
private const byte kMotorolaMark = 0x4d;
private const ushort kTiffMagicNumber = 42;


private bool IsTiff(Stream stm)
{
    stm.Seek(0);
    if (stm.Length < kMinimumTiffSize)
        return false;
    byte[] header = new byte[kHeaderSize];

    stm.Read(header, 0, header.Length);

    if (header[0] != header[1] || (header[0] != kIntelMark && header[0] != kMotorolaMark))
        return false;
    bool isIntel = header[0] == kIntelMark;

    ushort magicNumber = ReadShort(stm, isIntel);
    if (magicNumber != kTiffMagicNumber)
        return false;
    return true;
}

private ushort ReadShort(Stream stm, bool isIntel)
{
    byte[] b = new byte[2];
    _stm.Read(b, 0, b.Length);
    return ToShort(_isIntel, b[0], b[1]);
}

private static ushort ToShort(bool isIntel, byte b0, byte b1)
{
    if (isIntel)
    {
        return (ushort)(((int)b1 << 8) | (int)b0);
    }
    else
    {
        return (ushort)(((int)b0 << 8) | (int)b1);
    }
}

我破解了一些更通用的代码来得到这个。

对于PDF,我有如下代码:

public bool IsPdf(Stream stm)
{
    stm.Seek(0, SeekOrigin.Begin);
    PdfToken token;
    while ((token = GetToken(stm)) != null) 
    {
        if (token.TokenType == MLPdfTokenType.Comment) 
        {
            if (token.Text.StartsWith("%PDF-1.")) 
                return true;
        }
        if (stm.Position > 1024)
            break;
    }
    return false;
}

现在,GetToken()是对扫描器的调用,它将流标记为PDF标记。这不是无关紧要的,所以我不打算在这里粘贴它。我使用记号赋予器而不是子字符串来避免类似这样的问题:

% the following is a PostScript file, NOT a PDF file
% you'll note that in our previous version, it started with %PDF-1.3,
% incorrectly marking it as a PDF
%
clippath stroke showpage

上面的代码片段将此代码标记为不是PDF,而更简单的代码块将错误地将其标记为PDF。

我还应该指出,当前的ISO规范缺少以前Adobe拥有的规范中的实现说明。最重要的是,来自PDF参考1.6版:

Acrobat viewers require only that the header appear somewhere within
the first 1024 bytes of the file.
票数 22
EN

Stack Overflow用户

发布于 2010-04-29 01:55:43

TIFF可以通过在第一个字节http://local.wasp.uwa.edu.au/~pbourke/dataformats/tiff/处窥视来检测

头8个字节形成报头。它的前两个字节或者是"II“表示小端字节排序,或者是"MM”表示大端字节排序。

关于http://www.adobe.com/devnet/livecycle/articles/lc_pdf_overview_format.pdf

标题只包含一行标识

版本的内容。示例:%PDF-1.6

票数 8
EN

Stack Overflow用户

发布于 2010-04-29 02:08:00

阅读每种文件格式的规范将告诉您如何识别该格式的文件。

TIFF文件-检查字节1和2的0x4D4D或0x4949,检查字节2-3的值'42‘。

规范的第13页写道:

TIFF文件以8字节的图像文件头开始,包含以下信息:字节0-1:文件中使用的字节顺序。合法值为:“II”(4949.H)“MM”(4D4D.H)在“II”格式中,字节顺序始终是从最低有效字节到最高有效字节,对于16位和32位整数,这称为小端字节顺序。在“MM”格式中,对于16位和32位整数,字节顺序总是从最高有效位到最低有效位。这称为big-endian字节顺序。字节2-3是一个任意但仔细选择的数字(42),它进一步将文件标识为TIFF文件。字节顺序取决于字节0-1的值。

PDF文件以PDF版本开头,后跟几个二进制字节。(我认为您现在必须购买当前版本的ISO规范。)

第7.5.2节

文件的第一行应是由5个字符组成的标头% PDF -,后跟格式为1.N的版本号,其中N是介于0和7之间的数字。符合要求的阅读器应接受具有以下任何标头的文件:%PDF-1.0、%PDF-1.1、%PDF-1.2、%PDF-1.3、%PDF-1.4、%PDF-1.5、%PDF-1.6、% PDF -1.7从PDF 1.4开始,应使用文档目录字典中的版本条目(通过文件尾部中的根条目,如7.5.5,“文件尾部”中所述),如果存在,则应使用该版本条目,而不是标题中指定的版本。

如果PDF文件像大多数文件一样包含二进制数据(请参阅7.2,“词汇约定”),则标题行后面应紧跟一个注释行,其中至少包含四个二进制字符,即代码为128或更大的字符。这确保了文件传输应用程序的正确行为,这些应用程序检查文件开头附近的数据,以确定是将文件内容视为文本还是二进制。

当然,您可以通过检查更多特定于文件的项来对每个文件进行“更深层次”的检查。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2731917

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档