Терпите меня, поскольку я был брошен в середину этого проекта, не зная весь фон. Если Вы имеете вопросы 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
Действительно ли эта проблема легче, чем я думаю, или действительно ли это столь противно, как я ожидаю?
Хорошо, достаточно людей понимают это неправильно, поэтому я собираюсь опубликовать некоторый код, который у меня есть для идентификации 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.
Чтение спецификации для каждого формата файла расскажет вам, как идентифицировать файлы этого формата.
Файлы 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 или больше. Это обеспечивает правильное поведение приложений для передачи файлов , которые проверяют данные около начала файла, чтобы определить, обрабатывать ли содержимое файла как текст или как двоичный.
Конечно, вы можете провести «более глубокую» проверку каждого файла, проверив больше элементов, относящихся к конкретному файлу.
Вам нужно будет написать ashx, чтобы получить запрошенный файл.
тогда ваш обработчик должен прочитать первые несколько байтов (или около того), чтобы определить, какой тип файла на самом деле - PDF и TIFF имеют «магические числа» в начале файла, которые вы можете использовать для определения этого, затем установите соответствующие заголовки ответов.
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
Доступен очень полезный список сигнатур файлов, известных как «магические числа» Гэри Кесслера http://www.garykessler.net/library/file_sigs.html
Внутренне информация заголовка файла должна помочь. если вы открываете файл низкого уровня, такой как 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";
Если вы пойдете сюда, вы увидите, что TIFF обычно начинается с "магических чисел" 0x49 0x49 0x2A 0x00 (также даны некоторые другие определения), что является первыми 4 байтами файла.
Поэтому просто используйте эти первые 4 байта, чтобы определить, является ли файл TIFF или нет.
EDIT, возможно, лучше сделать это по-другому, и сначала определить PDF. Магические числа для PDF более стандартизированы: Как любезно указал Plinth, они начинаются с "%PDF" где-то в первых 1024 байтах (0x25 0x50 0x44 0x46). source