Js中FileReader讀取文件內(nèi)容方法詳解(async/await)
要通過FileReader判斷上傳的文件是否為圖片,可以使用FileReader讀取文件內(nèi)容,并判斷文件的MIME類型是否為圖片類型。
以下是一個(gè)示例代碼,可以在文件上傳時(shí)觸發(fā)change事件,并檢查上傳的文件是否為圖片類型:
<input type="file" id="fileInput" onchange="checkFile(event)">
function checkFile(event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = function() {
const uint = new Uint8Array(reader.result);
let bytes = [];
uint.forEach((byte) => {
bytes.push(byte.toString(16));
})
const hex = bytes.join('').toUpperCase();
const fileType = getFileType(hex);
if (fileType !== 'image') {
alert('Please upload an image file');
return;
}
getImageSize(file);
}
reader.readAsArrayBuffer(file);
}
function getFileType(hex) {
const fileTypes = {
'FFD8FF': 'image/jpeg',
'89504E': 'image/png',
'474946': 'image/gif',
'424D': 'image/bmp'
};
const fileTypeHex = hex.slice(0, 6);
const fileType = Object.keys(fileTypes).find(key => key === fileTypeHex);
return fileType ? fileTypes[fileType].split('/')[0] : 'unknown';
}
function getImageSize(file) {
const img = new Image();
img.onload = function() {
const width = img.width;
const height = img.height;
console.log('Image size: ', width, ' x ', height);
}
img.src = URL.createObjectURL(file);
}
上面的代碼首先使用FileReader讀取上傳的文件,并將文件內(nèi)容轉(zhuǎn)換為Uint8Array類型。然后,它將文件內(nèi)容的前6個(gè)字節(jié)轉(zhuǎn)換為十六進(jìn)制字符串,并使用該字符串獲取文件類型。如果文件類型不是圖片,則彈出警告消息并返回。
如果文件類型是圖片,則使用Image對象獲取圖片的寬度和高度。在getImageSize函數(shù)中,我們創(chuàng)建一個(gè)Image對象,并將其src屬性設(shè)置為URL.createObjectURL(file)以加載文件內(nèi)容。當(dāng)圖像加載完成時(shí),它將觸發(fā)onload事件處理程序,該處理程序?qū)@取圖像的寬度和高度。
要使用FileReader獲取音頻或視頻文件的時(shí)長,需要通過FileReader讀取文件并將其轉(zhuǎn)換為Blob對象,然后將Blob對象傳遞給一個(gè)新創(chuàng)建的HTML5音頻或視頻元素。
以下是一個(gè)獲取音頻或視頻文件時(shí)長的示例代碼:
<input type="file" id="fileInput" onchange="getDuration(event)">
<script>
function getDuration(event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = function() {
const blob = new Blob([reader.result], { type: file.type });
const mediaElement = document.createElement(file.type.startsWith('audio') ? 'audio' : 'video');
mediaElement.onloadedmetadata = function() {
console.log('Duration:', mediaElement.duration);
}
mediaElement.src = URL.createObjectURL(blob);
}
reader.readAsArrayBuffer(file);
}
</script>
上面的代碼中,我們首先通過FileReader讀取用戶選擇的文件,并將其轉(zhuǎn)換為Blob對象。我們還創(chuàng)建了一個(gè)新的HTML5音頻或視頻元素,具體取決于文件的MIME類型。然后我們?yōu)樵撛氐膐nloadedmetadata事件處理程序設(shè)置一個(gè)函數(shù),該函數(shù)在元數(shù)據(jù)加載完成后將打印出元素的duration屬性值,即音頻或視頻文件的時(shí)長。
最后,我們將Blob對象的URL分配給mediaElement的src屬性,以便瀏覽器可以加載媒體文件。在元數(shù)據(jù)加載完成后,它將自動(dòng)調(diào)用onloadedmetadata事件處理程序,我們將在這里獲取音頻或視頻文件的時(shí)長。
要同步獲取音頻或視頻文件的時(shí)長,您可以使用HTML5中的MediaMetadata API。MediaMetadata API是一個(gè)新的API,用于獲取媒體文件的元數(shù)據(jù),其中包括媒體文件的時(shí)長。
以下是一個(gè)使用MediaMetadata API同步獲取音頻或視頻文件時(shí)長的示例代碼:
<input type="file" id="fileInput" onchange="getDuration(event)">
<script>
async function getDuration(event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = async function() {
const blob = new Blob([reader.result], { type: file.type });
const mediaElement = document.createElement(file.type.startsWith('audio') ? 'audio' : 'video');
mediaElement.src = URL.createObjectURL(blob);
await mediaElement.play();
const metadata = mediaElement.getMetadata();
console.log('Duration:', metadata.duration);
}
reader.readAsArrayBuffer(file);
}
</script>上面的代碼中,我們首先通過FileReader讀取用戶選擇的文件,并將其轉(zhuǎn)換為Blob對象。我們還創(chuàng)建了一個(gè)新的HTML5音頻或視頻元素,具體取決于文件的MIME類型。然后我們將Blob對象的URL分配給mediaElement的src屬性,以便瀏覽器可以加載媒體文件。
在文件加載完成后,我們使用MediaMetadata API中的play()方法開始播放媒體文件。由于該方法返回一個(gè)promise,因此我們使用await關(guān)鍵字等待該promise完成。在媒體文件播放期間,MediaMetadata API會(huì)自動(dòng)獲取媒體文件的元數(shù)據(jù),其中包括媒體文件的時(shí)長。最后,我們可以使用getMetadata()方法獲取元數(shù)據(jù),并打印出音頻或視頻文件的時(shí)長。
請注意,MediaMetadata API目前不受所有瀏覽器的支持,因此在使用它時(shí)請務(wù)必檢查瀏覽器兼容性。
要在FileReader獲取完圖片長寬后執(zhí)行后續(xù)語句,您可以將后續(xù)語句放在FileReader的onload事件處理程序中。
onload事件處理程序會(huì)在文件讀取完成后立即執(zhí)行,因此您可以在其中獲取圖片的長寬,并執(zhí)行后續(xù)語句。
以下是一個(gè)示例代碼:
<input type="file" id="fileInput" onchange="getImageSize(event)">
<script>
function getImageSize(event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = function() {
const image = new Image();
image.onload = function() {
const width = this.width;
const height = this.height;
console.log('Image size:', width, height);
// 執(zhí)行后續(xù)語句
}
image.src = reader.result;
}
reader.readAsDataURL(file);
}
</script>
上面的代碼中,我們首先通過FileReader讀取用戶選擇的文件,并將其轉(zhuǎn)換為數(shù)據(jù)URL。然后,我們創(chuàng)建了一個(gè)新的Image對象,并在其onload事件處理程序中獲取圖像的寬度和高度。最后,我們將數(shù)據(jù)URL分配給圖像對象的src屬性,以便瀏覽器可以加載圖像文件。
當(dāng)圖像加載完成后,onload事件處理程序?qū)?zhí)行,并打印出圖像的寬度和高度。您可以在此處添加后續(xù)語句來執(zhí)行您需要在獲取圖像大小后執(zhí)行的任何操作。
如果您需要在FileReader獲取完圖片長寬后執(zhí)行的后續(xù)語句不在onload事件處理程序內(nèi)部執(zhí)行,而是在onload事件處理程序之后執(zhí)行,您可以將這些后續(xù)語句封裝到一個(gè)函數(shù)中,并在onload事件處理程序中調(diào)用該函數(shù),如下所示:
<input type="file" id="fileInput" onchange="getImageSize(event)">
<script>
function getImageSize(event) {
const file = event.target.files[0];
const reader = new FileReader();
reader.onload = function() {
const image = new Image();
image.onload = function() {
const width = this.width;
const height = this.height;
console.log('Image size:', width, height);
handleImageSize(width, height); // 調(diào)用后續(xù)處理函數(shù)
}
image.src = reader.result;
}
reader.readAsDataURL(file);
}
function handleImageSize(width, height) {
// 在這里執(zhí)行需要在獲取圖像大小后執(zhí)行的操作
console.log('Image size is ready');
}
</script>
在上面的代碼中,我們將后續(xù)語句封裝到名為handleImageSize的函數(shù)中,并在圖像的onload事件處理程序中調(diào)用它。由于onload事件處理程序是異步的,因此可以在圖像加載完成后執(zhí)行后續(xù)語句。
當(dāng)onload事件處理程序完成后,將調(diào)用handleImageSize函數(shù),并在其中執(zhí)行需要在獲取圖像大小后執(zhí)行的操作。在這個(gè)例子中,我們只是簡單地在控制臺(tái)輸出了一條消息。
請注意,如果您需要在多個(gè)onload事件處理程序中執(zhí)行后續(xù)語句,則必須確保它們是按照正確的順序執(zhí)行的。否則可能會(huì)導(dǎo)致錯(cuò)誤的行為。
您也可以使用async/await來處理FileReader獲取圖片長寬的異步操作。
下面是一個(gè)示例代碼,使用async/await在獲取圖片大小后執(zhí)行后續(xù)操作:
async function getImageSize(file) {
const reader = new FileReader();
reader.readAsDataURL(file);
await new Promise((resolve, reject) => {
reader.onload = resolve;
reader.onerror = reject;
});
const image = new Image();
image.src = reader.result;
await new Promise((resolve, reject) => {
image.onload = resolve;
image.onerror = reject;
});
const width = image.width;
const height = image.height;
console.log('Image size:', width, height);
// 執(zhí)行后續(xù)操作
}
在上面的代碼中,我們首先將FileReader對象讀取的數(shù)據(jù)轉(zhuǎn)換為數(shù)據(jù)URL,并使用Promise等待讀取操作完成。然后,我們創(chuàng)建了一個(gè)新的Image對象,并使用Promise等待圖像加載完成。最后,我們獲取圖像的寬度和高度,并執(zhí)行需要在獲取圖像大小后執(zhí)行的操作。
請注意,async/await在這里用于等待異步操作完成,并在操作完成后執(zhí)行后續(xù)語句。這個(gè)示例代碼中的getImageSize函數(shù)是一個(gè)異步函數(shù),可以使用await等待異步操作完成。
如果您需要在多個(gè)onload事件處理程序中執(zhí)行后續(xù)語句,則必須使用Promise等待這些異步操作完成,并確保它們是按照正確的順序執(zhí)行的。否則可能會(huì)導(dǎo)致錯(cuò)誤的行為。
您可以使用async/await和FileReader對象的readAsArrayBuffer方法來獲取文件類型。
下面是一個(gè)示例代碼,使用async/await同步獲取文件類型:
async function getFileType(file) {
const reader = new FileReader();
reader.readAsArrayBuffer(file.slice(0, 4));
await new Promise((resolve, reject) => {
reader.onload = resolve;
reader.onerror = reject;
});
const buffer = reader.result;
const view = new DataView(buffer);
const type = view.getUint32(0, false);
switch(type) {
case 0x89504E47:
return 'image/png';
case 0xFFD8FFE0:
case 0xFFD8FFE1:
case 0xFFD8FFE2:
return 'image/jpeg';
case 0x47494638:
return 'image/gif';
case 0x49443303:
return 'audio/mp3';
case 0x57415645:
return 'audio/wav';
case 0x4D546864:
return 'audio/midi';
case 0x666F6D73:
return 'video/quicktime';
case 0x3026B275:
return 'video/wmv';
case 0x464C5601:
return 'video/flv';
default:
return 'unknown';
}
}
在上面的代碼中,我們使用FileReader對象的readAsArrayBuffer方法讀取文件的前4個(gè)字節(jié),并使用DataView對象讀取文件類型。然后,我們使用switch語句判斷文件類型,并返回對應(yīng)的 MIME 類型。
請注意,await用于等待異步操作完成,并在操作完成后執(zhí)行后續(xù)語句。getFileType函數(shù)是一個(gè)異步函數(shù),可以使用await等待異步操作完成。
最后,我們可以在需要獲取文件類型的地方調(diào)用該函數(shù),如下所示:
const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', async function() {
const file = fileInput.files[0];
const fileType = await getFileType(file);
console.log('File type:', fileType);
// 執(zhí)行后續(xù)操作
});
在上面的代碼中,我們監(jiān)聽文件選擇器的change事件,并在事件處理程序中調(diào)用getFileType函數(shù),等待獲取文件類型,并執(zhí)行需要在獲取文件類型后執(zhí)行的后續(xù)操作。
您可以使用async/await和FileReader對象的readAsDataURL方法來判斷是否是圖片,并獲取圖片的寬高。
下面是一個(gè)示例代碼,使用async/await判斷是否是圖片,并獲取圖片的寬高:
async function getImageWidthAndHeight(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = async function(e) {
const image = new Image();
image.src = e.target.result;
image.onload = function() {
resolve({ width: this.width, height: this.height });
};
image.onerror = reject;
};
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
在上面的代碼中,我們使用FileReader對象的readAsDataURL方法將文件讀取為一個(gè)data:URL,并使用Image對象的onload事件獲取圖片的寬高。如果讀取文件或加載圖片時(shí)出現(xiàn)錯(cuò)誤,則使用onerror事件返回錯(cuò)誤。
請注意,await用于等待異步操作完成,并在操作完成后執(zhí)行后續(xù)語句。getImageWidthAndHeight函數(shù)是一個(gè)異步函數(shù),可以使用await等待異步操作完成。
最后,我們可以在需要獲取圖片寬高的地方調(diào)用該函數(shù),如下所示:
const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', async function() {
const file = fileInput.files[0];
const fileType = await getFileType(file);
if (fileType.startsWith('image/')) {
const { width, height } = await getImageWidthAndHeight(file);
console.log('Image width:', width, 'height:', height);
// 執(zhí)行后續(xù)操作
} else {
console.log('Not an image file');
}
}); 在上面的代碼中,我們先使用getFileType函數(shù)判斷文件是否為圖片,如果是圖片,則使用getImageWidthAndHeight函數(shù)獲取圖片的寬高,并執(zhí)行需要在獲取圖片寬高后執(zhí)行的后續(xù)操作。如果不是圖片,則打印錯(cuò)誤信息。
可以使用JavaScript中的數(shù)學(xué)運(yùn)算和字符串操作來將時(shí)長從小數(shù)形式轉(zhuǎn)換為時(shí)分秒形式。下面是一種實(shí)現(xiàn)方法:
// 定義時(shí)長為134.73913秒
const durationInSeconds = 134.73913;
// 計(jì)算小時(shí)、分鐘和秒數(shù)
const hours = Math.floor(durationInSeconds / 3600);
const minutes = Math.floor((durationInSeconds - (hours * 3600)) / 60);
const seconds = Math.floor(durationInSeconds - (hours * 3600) - (minutes * 60));
// 格式化輸出
const formattedDuration = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
console.log(formattedDuration); // 輸出 00:02:14
這段代碼首先將時(shí)長定義為134.73913秒。然后使用數(shù)學(xué)運(yùn)算計(jì)算出時(shí)、分、秒數(shù)。最后使用字符串操作將時(shí)、分、秒數(shù)格式化成時(shí)分秒形式,并輸出到控制臺(tái)。輸出結(jié)果為 00:02:14,表示時(shí)長為2分14秒。
使用 FileReader 和 async/await 可以異步讀取文件并獲取文件類型。下面是一個(gè)例子:
async function getFileType(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = function() {
const arr = (new Uint8Array(reader.result)).subarray(0, 4);
let header = '';
for(let i = 0; i < arr.length; i++) {
header += arr[i].toString(16);
}
switch (header) {
case '89504e47':
resolve('image/png');
break;
case '47494638':
resolve('image/gif');
break;
case 'ffd8ffe0':
case 'ffd8ffe1':
case 'ffd8ffe2':
resolve('image/jpeg');
break;
default:
resolve('unknown');
break;
}
};
reader.readAsArrayBuffer(file);
});
}
這段代碼定義了一個(gè) getFileType 函數(shù),接受一個(gè) File 對象作為參數(shù),并返回一個(gè) Promise 對象。在函數(shù)內(nèi)部,我們創(chuàng)建了一個(gè) FileReader 對象,并設(shè)置了它的 onload 事件處理程序,以便在文件讀取完成后獲取文件類型。我們使用 Uint8Array 數(shù)組讀取文件的前4個(gè)字節(jié),將其轉(zhuǎn)換為16進(jìn)制字符串,并根據(jù)特定的字節(jié)碼匹配文件類型。最后,我們使用 Promise 的 resolve 方法返回文件類型。
使用該函數(shù)的例子:
async function test() {
const file = new File(['test'], 'test.png', {type: 'image/png'});
const fileType = await getFileType(file);
console.log(fileType); // 輸出 'image/png'
}
test();
在這個(gè)例子中,我們創(chuàng)建了一個(gè)假的 File 對象,將其類型設(shè)置為 'image/png',并將其作為參數(shù)傳遞給 getFileType 函數(shù)。通過 await 關(guān)鍵字等待函數(shù)的結(jié)果,獲取文件類型,并輸出到控制臺(tái)。輸出結(jié)果為 'image/png',表示文件的類型為 PNG 圖像。
可以通過文件的擴(kuò)展名或者文件頭信息(即文件的開頭幾個(gè)字節(jié))來判斷文件類型。下面是一個(gè)簡單的判斷圖片、視頻和音頻文件類型的例子:
function getFileType(file) {
// 獲取文件名和擴(kuò)展名
const fileName = file.name;
const extension = fileName.slice((fileName.lastIndexOf('.') - 1 >>> 0) + 2).toLowerCase();
// 根據(jù)擴(kuò)展名判斷文件類型
switch (extension) {
case 'jpg':
case 'jpeg':
case 'png':
case 'gif':
case 'bmp':
return 'image';
case 'mp4':
case 'avi':
case 'wmv':
case 'mov':
case 'flv':
return 'video';
case 'mp3':
case 'wav':
case 'ogg':
return 'audio';
default:
return 'unknown';
}
}
在這個(gè)例子中,我們定義了一個(gè) getFileType 函數(shù),接受一個(gè) File 對象作為參數(shù),并返回一個(gè)字符串,表示文件的類型。在函數(shù)內(nèi)部,我們先通過文件名獲取文件的擴(kuò)展名,并將其轉(zhuǎn)換為小寫字母。然后根據(jù)擴(kuò)展名判斷文件類型,返回對應(yīng)的字符串。如果擴(kuò)展名無法識(shí)別,返回 'unknown'。
注意,這種方式只是簡單的根據(jù)擴(kuò)展名來判斷文件類型,有些文件可能沒有擴(kuò)展名,或者擴(kuò)展名被篡改,此時(shí)就無法正確判斷文件類型。為了更準(zhǔn)確地判斷文件類型,我們可以通過讀取文件頭信息來獲取更詳細(xì)的信息。前面提到的 getFileType 函數(shù)可以改寫成異步函數(shù),并通過 FileReader 對象讀取文件頭信息來判斷文件類型,示例代碼如下:
async function getFileType(file) {
const reader = new FileReader();
reader.readAsArrayBuffer(file.slice(0, 4));
return new Promise(resolve => {
reader.onload = () => {
const buffer = reader.result;
const uint8Array = new Uint8Array(buffer);
let header = '';
for (let i = 0; i < uint8Array.length; i++) {
header += uint8Array[i].toString(16);
}
switch (header) {
case '89504e47':
resolve('image/png');
break;
case '47494638':
resolve('image/gif');
break;
case 'ffd8ffe0':
case 'ffd8ffe1':
case 'ffd8ffe2':
resolve('image/jpeg');
break;
case '494433':
resolve('audio/mp3');
break;
case '524946':
resolve('audio/wav');
break;
case '4f676753':
resolve('audio/ogg');
break;
case '66747970':
resolve('video/mp4');
break;
case '774d5634':
resolve('video/webm');
break;
case '00018':
resolve('video/mov');
break;
default:
resolve('unknown');
break;
}
};
});
}
在這個(gè)例子中,我們定義了一個(gè)異步函數(shù) getFileType,接受一個(gè) File 對象作為參數(shù),并返回一個(gè) Promise 對象,最終返回一個(gè)字符串,表示文件的類型。在函數(shù)內(nèi)部,我們先創(chuàng)建一個(gè) FileReader 對象,并通過 readAsArrayBuffer 方法讀取文件的前四個(gè)字節(jié)(也就是文件頭信息)。然后在 onload 回調(diào)函數(shù)中,將讀取的字節(jié)轉(zhuǎn)換為 16 進(jìn)制字符串,并根據(jù)不同的字符串值判斷文件類型,返回對應(yīng)的 MIME 類型。如果無法識(shí)別文件類型,返回 'unknown'。
注意,這種方式雖然可以更準(zhǔn)確地判斷文件類型,但也有一些局限性。不同的文件格式可能有不同的文件頭信息,如果要判斷所有的文件類型,需要處理大量的情況,代碼會(huì)比較復(fù)雜。而且有些文件頭信息也可能被篡改,此時(shí)也無法正確判斷文件類型。所以在實(shí)際應(yīng)用中,需要根據(jù)具體的需求和情況來選擇合適的方式來判斷文件類型。
總結(jié)
到此這篇關(guān)于Js中FileReader讀取文件內(nèi)容方法的文章就介紹到這了,更多相關(guān)Js FileReader讀取文件內(nèi)容方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實(shí)現(xiàn)計(jì)算圓周率到小數(shù)點(diǎn)后100位的方法示例
這篇文章主要介紹了JavaScript實(shí)現(xiàn)計(jì)算圓周率到小數(shù)點(diǎn)后100位的方法,簡單分析了圓周率計(jì)算的原理并結(jié)合實(shí)例形式給出了javascript計(jì)算圓周率的具體操作技巧,需要的朋友可以參考下2018-05-05
JS實(shí)現(xiàn)網(wǎng)頁上隨機(jī)產(chǎn)生超鏈接地址的方法
這篇文章主要介紹了JS實(shí)現(xiàn)網(wǎng)頁上隨機(jī)產(chǎn)生超鏈接地址的方法,涉及JavaScript隨機(jī)數(shù)的相關(guān)使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11
微信小程序調(diào)用wx.getImageInfo遇到的坑解決
這篇文章主要介紹了微信小程序調(diào)用wx.getImageInfo遇到的坑解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05

