Js中FileReader讀取文件內(nèi)容方法詳解(async/await)
要通過FileReader判斷上傳的文件是否為圖片,可以使用FileReader讀取文件內(nèi)容,并判斷文件的MIME類型是否為圖片類型。
以下是一個示例代碼,可以在文件上傳時觸發(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個字節(jié)轉(zhuǎn)換為十六進(jìn)制字符串,并使用該字符串獲取文件類型。如果文件類型不是圖片,則彈出警告消息并返回。
如果文件類型是圖片,則使用Image對象獲取圖片的寬度和高度。在getImageSize函數(shù)中,我們創(chuàng)建一個Image對象,并將其src屬性設(shè)置為URL.createObjectURL(file)以加載文件內(nèi)容。當(dāng)圖像加載完成時,它將觸發(fā)onload事件處理程序,該處理程序?qū)@取圖像的寬度和高度。
要使用FileReader獲取音頻或視頻文件的時長,需要通過FileReader讀取文件并將其轉(zhuǎn)換為Blob對象,然后將Blob對象傳遞給一個新創(chuàng)建的HTML5音頻或視頻元素。
以下是一個獲取音頻或視頻文件時長的示例代碼:
<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)建了一個新的HTML5音頻或視頻元素,具體取決于文件的MIME類型。然后我們?yōu)樵撛氐膐nloadedmetadata事件處理程序設(shè)置一個函數(shù),該函數(shù)在元數(shù)據(jù)加載完成后將打印出元素的duration屬性值,即音頻或視頻文件的時長。
最后,我們將Blob對象的URL分配給mediaElement的src屬性,以便瀏覽器可以加載媒體文件。在元數(shù)據(jù)加載完成后,它將自動調(diào)用onloadedmetadata事件處理程序,我們將在這里獲取音頻或視頻文件的時長。
要同步獲取音頻或視頻文件的時長,您可以使用HTML5中的MediaMetadata
API。MediaMetadata
API是一個新的API,用于獲取媒體文件的元數(shù)據(jù),其中包括媒體文件的時長。
以下是一個使用MediaMetadata API同步獲取音頻或視頻文件時長的示例代碼:
<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)建了一個新的HTML5音頻或視頻元素,具體取決于文件的MIME類型。然后我們將Blob對象的URL分配給mediaElement的src屬性,以便瀏覽器可以加載媒體文件。
在文件加載完成后,我們使用MediaMetadata
API中的play()
方法開始播放媒體文件。由于該方法返回一個promise,因此我們使用await
關(guān)鍵字等待該promise完成。在媒體文件播放期間,MediaMetadata
API會自動獲取媒體文件的元數(shù)據(jù),其中包括媒體文件的時長。最后,我們可以使用getMetadata()
方法獲取元數(shù)據(jù),并打印出音頻或視頻文件的時長。
請注意,MediaMetadata
API目前不受所有瀏覽器的支持,因此在使用它時請務(wù)必檢查瀏覽器兼容性。
要在FileReader獲取完圖片長寬后執(zhí)行后續(xù)語句,您可以將后續(xù)語句放在FileReader的onload
事件處理程序中。
onload
事件處理程序會在文件讀取完成后立即執(zhí)行,因此您可以在其中獲取圖片的長寬,并執(zhí)行后續(xù)語句。
以下是一個示例代碼:
<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)建了一個新的Image
對象,并在其onload
事件處理程序中獲取圖像的寬度和高度。最后,我們將數(shù)據(jù)URL分配給圖像對象的src
屬性,以便瀏覽器可以加載圖像文件。
當(dāng)圖像加載完成后,onload
事件處理程序?qū)?zhí)行,并打印出圖像的寬度和高度。您可以在此處添加后續(xù)語句來執(zhí)行您需要在獲取圖像大小后執(zhí)行的任何操作。
如果您需要在FileReader獲取完圖片長寬后執(zhí)行的后續(xù)語句不在onload
事件處理程序內(nèi)部執(zhí)行,而是在onload
事件處理程序之后執(zhí)行,您可以將這些后續(xù)語句封裝到一個函數(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í)行的操作。在這個例子中,我們只是簡單地在控制臺輸出了一條消息。
請注意,如果您需要在多個onload
事件處理程序中執(zhí)行后續(xù)語句,則必須確保它們是按照正確的順序執(zhí)行的。否則可能會導(dǎo)致錯誤的行為。
您也可以使用async/await
來處理FileReader
獲取圖片長寬的異步操作。
下面是一個示例代碼,使用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)建了一個新的Image
對象,并使用Promise
等待圖像加載完成。最后,我們獲取圖像的寬度和高度,并執(zhí)行需要在獲取圖像大小后執(zhí)行的操作。
請注意,async/await
在這里用于等待異步操作完成,并在操作完成后執(zhí)行后續(xù)語句。這個示例代碼中的getImageSize
函數(shù)是一個異步函數(shù),可以使用await
等待異步操作完成。
如果您需要在多個onload
事件處理程序中執(zhí)行后續(xù)語句,則必須使用Promise
等待這些異步操作完成,并確保它們是按照正確的順序執(zhí)行的。否則可能會導(dǎo)致錯誤的行為。
您可以使用async/await
和FileReader
對象的readAsArrayBuffer
方法來獲取文件類型。
下面是一個示例代碼,使用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個字節(jié),并使用DataView
對象讀取文件類型。然后,我們使用switch
語句判斷文件類型,并返回對應(yīng)的 MIME 類型。
請注意,await
用于等待異步操作完成,并在操作完成后執(zhí)行后續(xù)語句。getFileType
函數(shù)是一個異步函數(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
方法來判斷是否是圖片,并獲取圖片的寬高。
下面是一個示例代碼,使用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
方法將文件讀取為一個data:URL
,并使用Image
對象的onload
事件獲取圖片的寬高。如果讀取文件或加載圖片時出現(xiàn)錯誤,則使用onerror
事件返回錯誤。
請注意,await
用于等待異步操作完成,并在操作完成后執(zhí)行后續(xù)語句。getImageWidthAndHeight
函數(shù)是一個異步函數(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ù)操作。如果不是圖片,則打印錯誤信息。
可以使用JavaScript中的數(shù)學(xué)運(yùn)算和字符串操作來將時長從小數(shù)形式轉(zhuǎn)換為時分秒形式。下面是一種實(shí)現(xiàn)方法:
// 定義時長為134.73913秒 const durationInSeconds = 134.73913; // 計算小時、分鐘和秒數(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
這段代碼首先將時長定義為134.73913秒。然后使用數(shù)學(xué)運(yùn)算計算出時、分、秒數(shù)。最后使用字符串操作將時、分、秒數(shù)格式化成時分秒形式,并輸出到控制臺。輸出結(jié)果為 00:02:14
,表示時長為2分14秒。
使用 FileReader 和 async/await 可以異步讀取文件并獲取文件類型。下面是一個例子:
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); }); }
這段代碼定義了一個 getFileType
函數(shù),接受一個 File
對象作為參數(shù),并返回一個 Promise 對象。在函數(shù)內(nèi)部,我們創(chuàng)建了一個 FileReader
對象,并設(shè)置了它的 onload
事件處理程序,以便在文件讀取完成后獲取文件類型。我們使用 Uint8Array
數(shù)組讀取文件的前4個字節(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();
在這個例子中,我們創(chuàng)建了一個假的 File
對象,將其類型設(shè)置為 'image/png',并將其作為參數(shù)傳遞給 getFileType
函數(shù)。通過 await
關(guān)鍵字等待函數(shù)的結(jié)果,獲取文件類型,并輸出到控制臺。輸出結(jié)果為 'image/png',表示文件的類型為 PNG 圖像。
可以通過文件的擴(kuò)展名或者文件頭信息(即文件的開頭幾個字節(jié))來判斷文件類型。下面是一個簡單的判斷圖片、視頻和音頻文件類型的例子:
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'; } }
在這個例子中,我們定義了一個 getFileType
函數(shù),接受一個 File
對象作為參數(shù),并返回一個字符串,表示文件的類型。在函數(shù)內(nèi)部,我們先通過文件名獲取文件的擴(kuò)展名,并將其轉(zhuǎn)換為小寫字母。然后根據(jù)擴(kuò)展名判斷文件類型,返回對應(yīng)的字符串。如果擴(kuò)展名無法識別,返回 'unknown'。
注意,這種方式只是簡單的根據(jù)擴(kuò)展名來判斷文件類型,有些文件可能沒有擴(kuò)展名,或者擴(kuò)展名被篡改,此時就無法正確判斷文件類型。為了更準(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; } }; }); }
在這個例子中,我們定義了一個異步函數(shù) getFileType
,接受一個 File
對象作為參數(shù),并返回一個 Promise 對象,最終返回一個字符串,表示文件的類型。在函數(shù)內(nèi)部,我們先創(chuàng)建一個 FileReader
對象,并通過 readAsArrayBuffer
方法讀取文件的前四個字節(jié)(也就是文件頭信息)。然后在 onload
回調(diào)函數(shù)中,將讀取的字節(jié)轉(zhuǎn)換為 16 進(jìn)制字符串,并根據(jù)不同的字符串值判斷文件類型,返回對應(yīng)的 MIME 類型。如果無法識別文件類型,返回 'unknown'。
注意,這種方式雖然可以更準(zhǔn)確地判斷文件類型,但也有一些局限性。不同的文件格式可能有不同的文件頭信息,如果要判斷所有的文件類型,需要處理大量的情況,代碼會比較復(fù)雜。而且有些文件頭信息也可能被篡改,此時也無法正確判斷文件類型。所以在實(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)計算圓周率到小數(shù)點(diǎn)后100位的方法示例
這篇文章主要介紹了JavaScript實(shí)現(xiàn)計算圓周率到小數(shù)點(diǎn)后100位的方法,簡單分析了圓周率計算的原理并結(jié)合實(shí)例形式給出了javascript計算圓周率的具體操作技巧,需要的朋友可以參考下2018-05-05JS實(shí)現(xiàn)網(wǎng)頁上隨機(jī)產(chǎn)生超鏈接地址的方法
這篇文章主要介紹了JS實(shí)現(xiàn)網(wǎng)頁上隨機(jī)產(chǎn)生超鏈接地址的方法,涉及JavaScript隨機(jī)數(shù)的相關(guān)使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-11-11微信小程序調(diào)用wx.getImageInfo遇到的坑解決
這篇文章主要介紹了微信小程序調(diào)用wx.getImageInfo遇到的坑解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05