如何检测文件是PDF还是TIFF?

evi*_*ack 18 c# pdf asp.net iis tiff

请耐心等待我,因为我已经被抛到了这个项目的中间而不知道所有的背景.如果你有WTF问题,请相信我,我也有.

这是一个场景:我有一堆文件驻留在IIS服务器上.他们没有文件扩展名.只是名称为"asda-2342-sd3rs-asd24-ut57"等的裸文件.没什么直观的.

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

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

问题:

由于这些文件都是无扩展名,因此我不得不强制IIS将所有内容作为TIFF提供.但是,如果我这样做,PDF文件将不会显示.我可以更改IIS以强制MIME类型为未知文件扩展名的PDF,但我有相反的问题.

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

这个问题比我想象的更容易,还是像我期待的那样令人讨厌?

pli*_*nth 22

好吧,有足够的人弄错了我要发布一些代码来识别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);
    }
}
Run Code Online (Sandbox Code Playgroud)

为了得到这个,我分解了一些更通用的代码.

对于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;
}
Run Code Online (Sandbox Code Playgroud)

现在,GetToken()是对扫描程序的调用,它将Stream标记为PDF标记.这不重要,所以我不打算在这里粘贴它.我正在使用tokenizer而不是查看substring来避免这样的问题:

% 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
Run Code Online (Sandbox Code Playgroud)

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

我还应该指出,目前的ISO规范没有以前Adobe拥有的规范中的实现说明.最重要的是从PDF参考版本1.6:

Acrobat viewers require only that the header appear somewhere within
the first 1024 bytes of the file.
Run Code Online (Sandbox Code Playgroud)

  • 什么是GetToken()和token.TokenType == MLPdfTokenType.Comment?任何代码?哪个库属于那个代码? (9认同)

And*_*rey 8

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

前8个字节构成标题.其前两个字节是用于小端字节排序的"II"或用于大端字节排序的"MM".

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

标题只包含一行标识PDF的版本.示例:%PDF-1.6


小智 5

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

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 位整数,字节顺序总是从最高有效到最低有效。这称为大端字节序。字节 2-3 任意但仔细选择的数字 (42),可进一步将文件标识为 TIFF 文件。字节顺序取决于字节 0-1 的值。

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

第 7.5.2 节

PDF 文件的第一行应是由 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 或更大的字符。这确保了文件传输应用程序的正确行为,这些应用程序检查文件开头附近的数据以确定是将文件内容视为文本还是二进制。

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