В повседневной работе загрузка файлов — очень распространенная функция. В некоторых случаях мы хотим иметь возможность ограничить тип загрузки файлов, например, ограничить загрузку изображений в формате PNG. Для решения этого вопроса рассмотримinput
элементальaccept
атрибут для ограничения типов загружаемых файлов:
<input type="file" id="inputFile" accept="image/png" />
Хотя эта схема может соответствовать большинству сценариев, если пользователь изменит суффикс изображения формата JPEG на.png
Если да, то это ограничение можно успешно преодолеть. Так как же решить эту проблему? Фактически, мы можем определить правильный тип файла, прочитав двоичные данные файла. Прежде чем представить конкретную схему реализации, брат Абао берет файл типа изображения в качестве примера, чтобы представить соответствующие знания.
1. Как просмотреть бинарные данные картинки
Для просмотра бинарных данных, соответствующих картинке, мы можем использовать некоторые готовые редакторы, например, под платформу Windows.WinHexили под платформу macOSSynalyze It! ProШестнадцатеричный редактор. Здесь мы используемSynalyze It! ProЭтот редактор в шестнадцатеричном формате для просмотра двоичных данных, соответствующих аватару Абаоге.
Следуйте «Дорога к бессмертному совершенствованию с полным стеком», чтобы прочитать 4 бесплатные электронные книги (всего более 30 000 загрузок) и 50 серий руководств по TS, изначально написанных А Баогэ.
2. Как различать типы картинок
Компьютер различает разные типы изображений не по суффиксу имени изображения, а по «магическому номеру».Для некоторых типов файлов содержимое первых нескольких байтов фиксировано, и по содержимому этих байтов можно судить о типе файла.
Магические числа, соответствующие распространенным типам изображений, показаны в следующей таблице:
тип файла | Расширение файла | магическое число |
---|---|---|
JPEG | jpg/jpeg | 0xFF D8 FF |
PNG | png | 0x89 50 4E 47 0D 0A 1A 0A |
GIF | gif | 0x47 49 46 38 (GIF8) |
BMP | bmp | 0x42 4D |
использовать то же самоеSynalyze It! ProЭтот редактор для проверки правильности типа аватара Брата Абао (abao.png):
Как видно из рисунка выше, первые 8 байт изображения типа PNG0x89 50 4E 47 0D 0A 1A 0A. когда ты ставишьabao.png
файл изменен наabao.jpeg
После этого откройте его в редакторе, чтобы просмотреть бинарное содержимое изображения, и вы обнаружите, что первые 8 байт файла остаются неизменными. но если вы используетеinput[type="file"]
Если вы используете поле ввода для чтения информации о файле, будут выведены следующие результаты:
очевидно черезРасширение файла или MIME-тип файлаНе удалось распознать правильный тип файла. Далее брат Абао расскажет, как обеспечить правильный тип изображения, читая двоичную информацию изображения при загрузке изображения.
3. Как определить тип изображения
3.1 Определение функции readBuffer
Получив файловый объект, мы можем прочитать содержимое файла через API FileReader. Поскольку нам не нужно читать всю информацию о файле, брат Абао инкапсулировалreadBuffer
Функция для чтения указанного диапазона двоичных данных из файла.
function readBuffer(file, start = 0, end = 2) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
resolve(reader.result);
};
reader.onerror = reject;
reader.readAsArrayBuffer(file.slice(start, end));
});
}
Для изображений типа PNG первые 8 байт файла0x89 50 4E 47 0D 0A 1A 0A. Поэтому, когда мы определяем, является ли выбранный файл изображением типа PNG, нам нужно только прочитать первые 8 байтов данных и определить, соответствует ли содержимое каждого байта один за другим.
3.2 Определение функции проверки
Для побайтового сравнения и лучшего повторного использования Brother Abao определяетcheck
функция:
function check(headers) {
return (buffers, options = { offset: 0 }) =>
headers.every(
(header, index) => header === buffers[options.offset + index]
);
}
3.3 Определение типа изображения PNG
На основании ранее определенногоreadBuffer
а такжеcheck
мы можем реализовать функцию обнаружения изображений PNG:
3.3.1 HTML-код
<div>
选择文件:<input type="file" id="inputFile" accept="image/*"
onchange="handleChange(event)" />
<p id="realFileType"></p>
</div>
3.3.2 JS-код
const isPNG = check([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]); // PNG图片对应的魔数
const realFileElement = document.querySelector("#realFileType");
async function handleChange(event) {
const file = event.target.files[0];
const buffers = await readBuffer(file, 0, 8);
const uint8Array = new Uint8Array(buffers);
realFileElement.innerText = `${file.name}文件的类型是:${
isPNG(uint8Array) ? "image/png" : file.type
}`;
}
После успешного запуска приведенного выше примера соответствующие результаты обнаружения показаны на следующем рисунке:
Как видно из приведенного выше рисунка, нам удалось успешно определить правильный формат изображения. Если вы хотите определить формат файла JPEG, вам нужно только определитьisJPEG
функция:
const isJPEG = check([0xff, 0xd8, 0xff])
Однако что, если вы хотите обнаружить файлы других типов, например файлы PDF? Здесь мы сначала используемSynalyze It! Proредактор для просмотра двоичного содержимого файла PDF:
Наблюдая за приведенным выше рисунком, мы видим, что первые 4 байта файла PDF0x25 50 44 46, соответствующая строка%PDF. Чтобы позволить пользователям более интуитивно определять тип обнаружения, Brother Abao определяетstringToBytes
функция:
function stringToBytes(string) {
return [...string].map((character) => character.charCodeAt(0));
}
на основеstringToBytes
функцию, мы можем легко определитьisPDF
функционируют следующим образом:
const isPDF = check(stringToBytes("%PDF"));
имеютisPDF
функция, вы реализовали функцию обнаружения файла PDF. Однако в реальной работе встречаются различные типы файлов, в этой ситуации можно использовать готовую третью библиотеку для реализации функции обнаружения файлов, напримерfile-typeэта библиотека.
Фактически, на основе двоичных данных файла, помимо определения типа файла, мы также можем прочитать метаданные, связанные с файлом, такие как размер, битовая глубина, тип цвета и алгоритм сжатия изображения. (abao.png) в качестве примера рассмотрим реальную ситуацию:
Хорошо, вот и все, как определять типы файлов во внешнем интерфейсе. В реальных проектах для сценариев загрузки файлов из соображений безопасности рекомендуется ограничивать типы загрузки файлов в процессе разработки. Для более строгих сценариев вы можете рассмотреть возможность использования метода, представленного Brother Abao, для проверки типа файла. Кроме того, если вам интересно, как внешний интерфейс обрабатывает двоичные данные, вы можете прочитатьИграйте с интерфейсным двоичным кодом.
Следуйте «Дорога полного стека», чтобы прочитать 4 бесплатные электронные книги (всего более 30 000 загрузок) и 11 руководств по Vue 3 для продвинутых пользователей.Друзья, которые хотят вместе изучать TS/Vue 3.0, могут добавить Abaoge WeChat —— semlinker.