Как обнаружить, если файлом является PDF или 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

Действительно ли эта проблема легче, чем я думаю, или действительно ли это столь противно, как я ожидаю?

18
задан eviljack 28 April 2010 в 17:50
поделиться

7 ответов

Хорошо, достаточно людей понимают это неправильно, поэтому я собираюсь опубликовать некоторый код, который у меня есть для идентификации 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 Reference, версия 1.6:

Acrobat viewers require only that the header appear somewhere within
the first 1024 bytes of the file.
22
ответ дан 30 November 2019 в 07:03
поделиться

Чтение спецификации для каждого формата файла расскажет вам, как идентифицировать файлы этого формата.

Файлы TIFF - проверьте байты 1 и 2 на наличие 0x4D4D или байты 0x4949 и 2–3 на значение «42».

Страница 13 спецификации гласит:

Файл TIFF начинается с 8-байтового заголовка файла изображения, содержащего следующую информацию: Байты 0-1: {{1 }} порядок байтов, используемый в файле. Допустимые значения : «II» (4949.H) «MM» (4D4D.H) В формате «II» порядок байтов всегда начинается с наименьшего { {1}} значащий байт до самого значащего байта, как для 16-битных, так и 32-битных целых чисел. Это называется порядком байтов с прямым порядком байтов . В формате «MM» порядок байтов всегда от наиболее значимого до наименее значимого для как 16-разрядных, так и 32-разрядных целых чисел. Этот называется порядком байтов с прямым порядком байтов. Байты 2–3 Произвольное, но тщательно подобранное число (42), которое в дальнейшем идентифицирует файл как файл TIFF. Порядок байтов зависит от значения байтов 0–1.

Файлы PDF начинаются с версии PDF, за которой следует несколько двоичных байтов. (Думаю, теперь вам необходимо приобрести спецификацию ISO для текущей версии.)

Раздел 7.5.2

Первая строка файла PDF должна быть заголовком, состоящим из 5 {{1 }} символы% 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, запись версии в словаре каталога документа (находится через корневую запись в папке {{1} файла) }} трейлер, как описано в 7.5.5, «Файл Трейлер»), если он присутствует, должен использоваться вместо версии, указанной в Заголовке.

Если файл PDF содержит двоичные данные, как большинство из них (см. 7.2, «Лексические соглашения»), за строкой заголовка должен сразу следовать комментарий { Строка {1}}, содержащая не менее четырех двоичных символов , то есть символов, коды которых составляют 128 или больше. Это обеспечивает правильное поведение приложений для передачи файлов , которые проверяют данные около начала файла, чтобы определить, обрабатывать ли содержимое файла как текст или как двоичный.

Конечно, вы можете провести «более глубокую» проверку каждого файла, проверив больше элементов, относящихся к конкретному файлу.

4
ответ дан 30 November 2019 в 07:03
поделиться

Вам нужно будет написать ashx, чтобы получить запрошенный файл.

тогда ваш обработчик должен прочитать первые несколько байтов (или около того), чтобы определить, какой тип файла на самом деле - PDF и TIFF имеют «магические числа» в начале файла, которые вы можете использовать для определения этого, затем установите соответствующие заголовки ответов.

0
ответ дан 30 November 2019 в 07:03
поделиться

TIFF можно обнаружить по первым байтам http://local.wasp.uwa.edu.au/~pbourke/dataformats/tiff/

Первые 8 байтов образуют заголовок. Первые два байта из которых либо {{ 1}} «II» для порядка байтов с прямым порядком байтов или «ММ» для порядка байтов с прямым порядком байтов.

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

Заголовок содержит только одну строку, которая определяет версию PDF. { {1}} Пример:% PDF-1.6

8
ответ дан 30 November 2019 в 07:03
поделиться

Доступен очень полезный список сигнатур файлов, известных как «магические числа» Гэри Кесслера http://www.garykessler.net/library/file_sigs.html

3
ответ дан 30 November 2019 в 07:03
поделиться

Внутренне информация заголовка файла должна помочь. если вы открываете файл низкого уровня, такой как StreamReader () или FOPEN (), посмотрите на первые два символа в файле ... Почти каждый тип файла имеет свою собственную подпись.

PDF always starts with "%P" (but more specifically would have like %PDF)
TIFF appears to start with "II"
Bitmap files with "BM"
Executable files with "MZ"

Мне тоже приходилось иметь дело с этим в прошлом ... также для предотвращения загрузки нежелательных файлов на данный сайт и немедленного прерывания его после проверки.

РЕДАКТИРОВАТЬ - Добавлен образец кода для чтения и проверки типов заголовков файлов

String fn = "Example.pdf";

StreamReader sr = new StreamReader( fn );
char[] buf = new char[5];
sr.Read( buf, 0, 4);
sr.Close();
String Hdr = buf[0].ToString()
    + buf[1].ToString()
    + buf[2].ToString()
    + buf[3].ToString()
    + buf[4].ToString();

String WhatType;
if (Hdr.StartsWith("%PDF"))
   WhatType = "PDF";
else if (Hdr.StartsWith("MZ"))
   WhatType = "EXE or DLL";
else if (Hdr.StartsWith("BM"))
   WhatType = "BMP";
else if (Hdr.StartsWith("?_"))
   WhatType = "HLP (help file)";
else if (Hdr.StartsWith("\0\0\1"))
   WhatType = "Icon (.ico)";
else if (Hdr.StartsWith("\0\0\2"))
   WhatType = "Cursor (.cur)";
else
   WhatType = "Unknown";
3
ответ дан 30 November 2019 в 07:03
поделиться

Если вы пойдете сюда, вы увидите, что TIFF обычно начинается с "магических чисел" 0x49 0x49 0x2A 0x00 (также даны некоторые другие определения), что является первыми 4 байтами файла.

Поэтому просто используйте эти первые 4 байта, чтобы определить, является ли файл TIFF или нет.

EDIT, возможно, лучше сделать это по-другому, и сначала определить PDF. Магические числа для PDF более стандартизированы: Как любезно указал Plinth, они начинаются с "%PDF" где-то в первых 1024 байтах (0x25 0x50 0x44 0x46). source

1
ответ дан 30 November 2019 в 07:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: