JavaScript判斷文件類型三種方法詳解
js判斷文件類型詳解
通過file的type屬性判斷
<input type="file" onchange="onchangecb(this)" />
<script>
function onchangecb(e) {
const file = e.files[0];
console.log(file.type);
}
</script>
像html中input標簽,就是根據(jù)選擇文件的后綴來生成一個File對象。
像下面的幾種文件:
txt文件:

jpg文件:

mp4文件:

使用文件后綴來判斷
function onchangecb(e) {
const file = e.files[0];
//獲取最后一個.的位置
const index= file.name.lastIndexOf(".");
//獲取后綴
const ext = file.name.substr(index+1);
console.log(ext);
}
在得到文件后綴名后,根據(jù)后綴即可判斷文件的類型(文件格式)。比如需要判斷一個文件是否是圖片格式,首先定義一個判斷函數(shù):
function isImage(ext) {
return [
'png', 'jpg', 'jpeg', 'bmp', 'gif', 'webp', 'psd', 'svg', 'tiff'].
indexOf(ext.toLowerCase()) !== -1;
}
雖然可以直接通過對象的type屬性或者文件后綴來獲取文件類型,但是如果強行修改文件后綴,同樣可以將其他類型的文件上傳至服務(wù)器,或者文件壓根就沒有后綴,那又要怎么判斷呢?因此前端需要使用一個更加合理的方式。
根據(jù)二進制流及文件頭來判斷
雖然文件后綴可以手動改,因此可以直接通過讀取文件的二進制來判斷。
通常來說固定類型的文件頭都是相同的,比如說jpeg的文件頭是FF D8 FF E0。
這里提供一些常用的文件頭:
const fileMap = {
JPEG: "FF D8 FF E0",
JPG: "FF D8 FF E1",
PNG: "89 50 4E 47",
GIF: "47 49 46 38",
TIFF: "49 49 2A 00",
BMP: "42 4D",
DWG: "41 43 31 30",
PSD: "38 42 50 53",
RTF: "7B 5C 72 74 66",
XML: "3C 3F 78 6D 6C",
HTML: "68 74 6D 6C 3E",
EML: "44 65 6C 69 76 65 72 79 2D 64 61 74 65 3A",
DBX: "CF AD 12 FE C5 FD 74 6F",
PST: "21 42 44 4E",
XLS: "D0 CF 11 E0",
DOC: "D0 CF 11 E0",
MDB: "53 74 61 6E 64 61 72 64 20 4A",
WPD: "FF 57 50 43",
PDF: "25 50 44 46 2D 31 2E",
QDF: "AC 9E BD 8F",
PWL: "E3 82 85 96",
ZIP: "50 4B 03 04",
RAR: "52 61 72 21",
WAV: "57 41 56 45",
AVI: "41 56 49 20",
RAM: "2E 72 61 FD",
RM: "2E 52 4D 46",
MPG: "00 00 01 BA",
MPG: "00 00 01 B3",
MOV: "6D 6F 6F 76",
ASF: "30 26 B2 75 8E 66 CF 11",
MID: "4D 54 68 64",
MP3: "49 44 33",
};
通過onchange方法獲取到選擇的文件后,使用FileReader讀取文件的二進制,之后判斷二進制的前幾位是否跟符合相應(yīng)類型文件的文件頭。
以下是一些使用文件頭來判斷文件類型的簡單代碼
// 判斷文件后綴與該文件內(nèi)容是否相同類型
async function isSameFileType(file) {
const suffix = getFileSuffix(file.name).toUpperCase();
const fileBlobString = await blobToString(file.slice(0, 14));
// 如果文件類型中沒有該類型,默認為false
if (!(suffix in fileMap)) {
return false;
}
return fileBlobString.includes(fileMap[suffix]);
}
async function blobToString(blob) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.onload = function () {
const ret = reader.result
.split("") // 分隔開
.map((v) => v.charCodeAt()) // 循環(huán)返回指定位置的字符的 Unicode 編碼
.map((v) => v.toString(16).toUpperCase()) // 返回十六進制格式
.map((v) => v.padStart(2, "0")) // 給空的那個填充 00 ,防止空缺
.join(" "); // 每個子節(jié)之間空格隔開
resolve(ret);
};
reader.readAsBinaryString(blob); // 調(diào)用之后觸發(fā)onload事件
});
// 二進制=》ascii碼=》轉(zhuǎn)成16進制字符串
}
// 獲取文件后綴
function getFileSuffix(filename) {
return filename.substring(filename.lastIndexOf(".") + 1, filename.length);
}
判斷是否是png類型:
async function isPng(file) {
// 同理
const ret = await blobToString(file.slice(0, 4));
const ispng = ret === fileMap.PNG;
return ispng;
}
當(dāng)然也可以針對圖片高寬進行限制:
在png二進制中,第18-20位是圖片的寬,22-24是高。
獲取圖片寬高:
function getRectByOffset(file, widthOffset, heightOffset, reverse) {
let width = await blobToString(file.slice(...widthOffset));
let height = await blobToString(file.slice(...heightOffset));
const w = parseInt(width.replace(" ", ""), 16);
const h = parseInt(height.replace(" ", ""), 16);
return { w, h };
}
修改一下之前判斷isPng的方法,加上高寬限制
const IMG_WIDTH_LIMIT = 1000;
const IMG_HEIGHT_LIMIT = 800
function isPng(file) {
// 同理
const ret = await this.blobToString(file.slice(0, 4));
const ispng = ret === fileMap.PNG;
if (ispng) {
const { w, h } = await this.getRectByOffset(file, [18, 20], [22, 24]);
console.log(`png 寬高 ${w},${h}`);
if (w > IMG_WIDTH_LIMIT || h > IMG_HEIGHT_LIMIT) {
this.$message.error(
"png圖片寬高不得超過 " + IMG_WIDTH_LIMIT + "和" + IMG_HEIGHT_LIMIT
);
return false;
}
}
return ispng;
}附:js已知文件路徑,通用獲取文件名、后綴、類型
代碼參考
// 選擇文件后返回 { resultData: '/storage/emulated/0/DCIM/Camera/IMG_20170703_133717.jpg' }
var path ='/storage/emulated/0/DCIM/Camera/IMG_20170703_133717.jpg' ;
var fileName = common.getFileNameByPath(path); // .jpg
console.log("文件名="+fileName);
var fileType=common.getFileTypeByPath(path); // jpg
console.log("文件類型="+fileType);
var fileExtension=common.getFileExtensionByPath(path); // .jpg
console.log("文件后綴="+fileExtension);
核心代碼
/**
* 作者: 丸子
* 描述: 自定義工具
*/
'use strict';
window.common = window.common || (function(exports) {
/*
* 已知文件路徑,獲取文件名xxx.doc
*/
exports.getFileNameByPath = function(path) {
var index = path.lastIndexOf("/"); // lastIndexOf("/") 找到最后一個 / 的位置
var fileName = path.substr(index + 1); // substr() 截取剩余的字符,即得文件名xxx.doc
return fileName;
};
/*
* 已知文件路徑,獲取文件類型doc
*/
exports.getFileTypeByPath = function(path) {
var index = path.lastIndexOf("."); // lastIndexOf("/") 找到最后一個 / 的位置
var fileType = path.substr(index + 1); // substr() 截取剩余的字符,即文件名doc
return fileType;
};
/*
* 已知文件路徑,獲取文件后綴.doc
*/
exports.getFileExtensionByPath = function(path) {
var index1 = path.lastIndexOf("."); // lastIndexOf("/") 找到最后一個 / 的位置
var index2 = path.length;
var fileExtension = path.substr(index1, index2); // substr() 截取剩余的字符,即文件名.doc
return fileExtension;
};
return exports;
})({});
總結(jié)
到此這篇關(guān)于JavaScript判斷文件類型三種方法的文章就介紹到這了,更多相關(guān)js判斷文件類型內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
最好用的二級聯(lián)動 原生js實現(xiàn)你值得擁有
二級聯(lián)動效果,實現(xiàn)方法有很多,不過其他文章中介紹的都比較籠統(tǒng),在本文有一個詳細的實現(xiàn)過程,使用原生js很容易理解,希望大家可以參考下2013-09-09
使用ionic(選項卡欄tab) icon(圖標) ionic上拉菜單(ActionSheet) 實現(xiàn)通訊錄界面切換實例
這篇文章主要介紹了使用ionic(選項卡欄tab) icon(圖標) ionic上拉菜單(ActionSheet) 實現(xiàn)通訊錄界面切換實例代碼,需要的朋友可以參考下2017-10-10

