Подтвердить что ты не робот

Как определить, является ли файл PDF или TIFF?

Пожалуйста, несите меня, поскольку меня бросили в середину этого проекта, не зная всего фона. Если у вас есть вопросы WTF, поверьте мне, у меня тоже есть.

Вот сценарий: у меня есть куча файлов, находящихся на сервере IIS. У них нет расширения файлов. Просто голые файлы с именами, такими как "asda-2342-sd3rs-asd24-ut57" и так далее. Ничего интуитивного.

Проблема в том, что мне нужно обслуживать файлы на странице ASP.NET(2.0) и отображать файлы tiff как tiff и PDF файлы в формате PDF. К сожалению, я не знаю, что именно, и мне нужно иметь возможность отображать их соответствующим образом в их соответствующих форматах.

Например, скажем, что есть два файла, которые мне нужно отображать, один - tiff, а один - PDF. На странице должно появиться изображение tiff и, возможно, ссылка, которая откроет PDF в новой вкладке/окне.

Проблема:

Поскольку эти файлы не имеют расширения, мне пришлось заставить IIS просто обслуживать все как TIFF. Но если я это сделаю, файлы PDF не будут отображаться. Я могу изменить IIS, чтобы заставить MIME-тип PDF для неизвестных расширений файлов, но у меня возникла бы обратная проблема.

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

Является ли эта проблема проще, чем я думаю, или она такая противная, как я ожидаю?

4b9b3361

Ответ 1

ОК, достаточно людей ошибаются, что я собираюсь опубликовать код, который я должен идентифицировать 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() - это вызов в сканер, который токенизирует Stream в 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.

Ответ 2

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

Ответ 3

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

TIFF файлы - проверьте байты 1 и 2 для 0x4D4D или 0x4949 и байты 2-3 для значения "42".

Страница 13 из спецификации читает:

Файл TIFF начинается с 8-байтного заголовок файла изображения, содержащий следующая информация: Байты 0-1: байтовый порядок, используемый в файле. легальный значения: "II" (4949.H) "MM" (4D4D.H) В формате "II" байт порядок всегда от наименьшего значительный байт до значительный байт, как для 16-битных, так и для 32-разрядные целые числа. Это называется little-endian byte order. В "ММ" формат, порядок байтов всегда от большинства значимых до наименее значимых для как 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, запись Версии в словарь каталога документов (расположен через запись Root в файлах трейлер, как описано в 7.5.5, "Файл Прицеп" ), если они имеются, должны использоваться вместо версии, указанной в Заголовок.

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

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

Ответ 5

Внутренне, информация заголовка файла должна помочь. если вы открываете файл низкого уровня, например 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"

Мне приходилось иметь дело с этим и в прошлом... также, чтобы предотвратить нежелательное скачивание нежелательных файлов на данный сайт и немедленное прерывание его после проверки.

EDIT - добавлен образец кода для чтения и тестирования типов заголовков файлов

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

Ответ 6

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

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

РЕДАКТИРОВАТЬ, возможно, лучше сделать это другим способом и сначала определить PDF. Магические числа для PDF более стандартизированы: поскольку Плинт любезно отметил, что они начинаются с "% PDF" где-то в первых 1024 байтах (0x25 0x50 0x44 0x46). источник

Ответ 7

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

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