最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript實(shí)現(xiàn)獲取圖片文件真實(shí)格式的示例代碼

 更新時(shí)間:2023年02月21日 11:23:44   作者:jimojianghu  
每種格式的圖片,都有自己特有的優(yōu)缺點(diǎn)以及數(shù)據(jù)結(jié)構(gòu),本篇博文的目的就是基于不同格式的圖像二進(jìn)制數(shù)據(jù),獲取到圖片的真實(shí)格式,感興趣的可以了解一下

前面博文有提到,當(dāng)前主流瀏覽器能支持的圖片格式,是七種:jpg、png、gif、bmp、ico、webp、svg,其中,前六種都是位圖,svg則是唯一的矢量圖。

每種格式的圖片,都有自己特有的優(yōu)缺點(diǎn)以及數(shù)據(jù)結(jié)構(gòu),本篇博文的目的就是基于不同格式的圖像二進(jìn)制數(shù)據(jù),獲取到圖片的真實(shí)格式。

常見(jiàn)方式判斷圖片格式

當(dāng)我們進(jìn)行前端開(kāi)發(fā),需要處理圖片上傳功能,針對(duì)圖片格式做判斷時(shí),常規(guī)的方法都是使用文件后綴名來(lái)判斷,如下代碼所示:

input.addEventListener('change', (e) => {
  const file = e.target.files[0]
  const format = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase()
}, false)

以上代碼,監(jiān)聽(tīng)上傳控件的事件,得到要上傳的文件信息,獲取文件名稱,然后通過(guò)獲取文件名稱截取文件后綴名,以后綴名作為圖片文件的格式。

這段代碼,大部分人都比較熟悉,也有很多場(chǎng)景下是這樣來(lái)判斷圖片格式的,但如果我們強(qiáng)行修改了文件的后綴名,則此方法就失效了。

我們知道gif格式圖片的位深度是8,如果我們強(qiáng)制把位深度為32的png格式的圖片后綴名改成gif,這個(gè)圖片文件依然可以正常使用:

上圖所示,就是將png格式文件后綴名改成了gif,圖片系統(tǒng)信息顯示格式為gif,但是位深度還是32,圖像本質(zhì)上還是png格式的。

這個(gè)時(shí)候,單純的通過(guò)后綴名來(lái)判斷圖片的格式,就不再準(zhǔn)確了,我們需要另外的方式來(lái)獲取圖片文件的真實(shí)格式。而這種方式就需要使用到前端二進(jìn)制相關(guān)的知識(shí),見(jiàn)前文介紹深入理解前端字節(jié)二進(jìn)制知識(shí)以及相關(guān)API。

修改后綴名的方式

  • 幾種位圖格式之間,是可以相互修改后綴名,圖片仍能正常使用
  • gif動(dòng)圖后綴名改成其他位圖格式,則動(dòng)效會(huì)失效,變成靜態(tài)圖
  • 位圖格式的后綴名如果改成矢量圖svg,則圖片失效,將無(wú)法使用
  • svg圖片文件后綴名改成位圖格式,圖片也將無(wú)法使用

圖像數(shù)據(jù)簡(jiǎn)單說(shuō)明

不同格式的圖像所存儲(chǔ)的數(shù)據(jù)是不一樣的,都有自己特殊的數(shù)據(jù)結(jié)構(gòu)。

依據(jù)各個(gè)格式圖像不同的數(shù)據(jù)結(jié)構(gòu),我們通過(guò)類型數(shù)組中的圖像數(shù)據(jù),就能判斷出圖片的真實(shí)格式。

  • 如jpg格式,它的圖像數(shù)據(jù)結(jié)構(gòu)中,最前面2個(gè)字節(jié)是一個(gè)固定取值 0xFFD8,第三個(gè)字節(jié)一般也是固定 0xFF。
  • 如png格式,它的圖像數(shù)據(jù)結(jié)構(gòu)中,最前面8個(gè)字節(jié)就是PNG文件署名域,可以很好的標(biāo)識(shí)出當(dāng)前圖像的格式就是PNG。
  • 如bmp格式,它的圖像數(shù)據(jù)結(jié)構(gòu)中,最前面14個(gè)字節(jié)存儲(chǔ)的是文件頭信息,而最前面2個(gè)字節(jié)存儲(chǔ)的就是文件類型:BM。
  • 如webp格式,需要從最前面移動(dòng)8個(gè)字節(jié)以后,取接下來(lái)的4個(gè)字節(jié)的信息,代表文件類型:WEBP

針對(duì)不同位圖的的數(shù)據(jù)判斷,可以使用下面表格列出的方式:

格式標(biāo)識(shí)的字節(jié)數(shù)對(duì)應(yīng)的十進(jìn)制值偏移量
jpg3255 216 2550
png8137 80 78 71 13 10 26 100
gif371, 73, 700
webp487, 69, 66, 808
ico40, 0, 1, 00
bmp266 770

其中,偏移量為0,表示取最前面幾個(gè)字節(jié)的數(shù)據(jù);webp的偏移量為8,表示從最前面移動(dòng)8個(gè)字節(jié)后,再取4個(gè)字節(jié)的標(biāo)識(shí)符。

上面的表格,已經(jīng)列出了當(dāng)前瀏覽器支持的位圖圖像,字節(jié)判斷標(biāo)識(shí),通過(guò)讀取相應(yīng)的數(shù)據(jù)做對(duì)比就得到了真實(shí)的格式。

以上幾種格式中,bmp、gif、webp取到的數(shù)據(jù),都能對(duì)應(yīng)各自特有的署名標(biāo)識(shí),前面有提到 BMWEBP,gif格式的則是 GIF??梢赃\(yùn)用字符編碼方面的知識(shí),如使用 String.fromCharCode 方法對(duì)數(shù)值進(jìn)行轉(zhuǎn)換,具體的前端字符編碼知識(shí)見(jiàn)前文前端開(kāi)發(fā)中需要搞懂的字符編碼

// bmp
String.fromCharCode(66) // B
String.fromCharCode(77) // M

// gif
String.fromCharCode(71) // G
String.fromCharCode(73) // I
String.fromCharCode(70) // F

// webp
String.fromCharCode(87) // W
String.fromCharCode(69) // E
String.fromCharCode(66) // B
String.fromCharCode(80) // P

gif格式的署名標(biāo)識(shí)是和版本號(hào)一起處理的,一般最前面6個(gè)字節(jié)標(biāo)識(shí): 'G'、'I'、'F'、'8'、'7(9)'、'a'。第5個(gè)字節(jié)可取值7或者9,代表兩個(gè)不同的版本,即1987年的版本和1989年的版本。

JS讀取圖片真實(shí)格式

當(dāng)我們了解了前端二進(jìn)制相關(guān)的知識(shí)后,就應(yīng)該知道圖片文件也是能通過(guò)WebAPI對(duì)象,讀取到對(duì)應(yīng)的數(shù)據(jù):

const reader = new FileReader()
reader.onload = () => {
  const imgArrayBuffer = reader.result
  const imgUint8Array = new Uint8Array(imgArrayBuffer)
}
reader.readAsArrayBuffer(file)

以上代碼,就是通過(guò) FileReader 對(duì)象讀取文件的數(shù)據(jù),這里是作為 ArrayBuffer 來(lái)讀取的,然后就可以轉(zhuǎn)換成類型數(shù)組進(jìn)行處理了。

讀取到圖片文件的 Uint8Array 類型數(shù)組數(shù)據(jù)后,根據(jù)上文表格中提到的格式字節(jié)數(shù)據(jù)標(biāo)識(shí),我們以jpg、bmp和webp為例:

imgUint8Array[0] === 66 && imgUint8Array[1] === 77 // bmp 格式
imgUint8Array[0] === 255 && imgUint8Array[1] === 216 && imgUint8Array[3] === 255 // jpg 格式
imgUint8Array[8] === 87 && imgUint8Array[9] === 69 && imgUint8Array[10] === 66 && imgUint8Array[10] === 80 // webp 格式

到此,就可以使用這種方式來(lái)讀取到圖片的真實(shí)格式,部分判斷代碼如下:

// 各格式對(duì)應(yīng)圖像數(shù)據(jù)的標(biāo)識(shí)數(shù)值
const IMAGEFORMATS = [
  { ext: 'png', data: [137, 80, 78, 71, 13, 10, 26, 10] },
  { ext: 'jpg', data: [255, 216, 255] },
  { ext: 'gif', data: [71, 73, 70] },
  { ext: 'ico', data: [0, 0, 1, 0] },
  { ext: 'bmp', data: [66, 77] },
  { ext: 'webp', data: [87, 69, 66, 80], offset: 8 }
]

// 循環(huán)判斷文件是否符合某個(gè)格式對(duì)應(yīng)的標(biāo)識(shí)數(shù)值
for (let i = 0; i < IMAGEFORMATS.length; i++) {
  const { data, offset, ext } = IMAGEFORMATS[i]
  if (isEqualFormatPrefix(imgUint8Array, data, offset)) {
    return ext
  }
}

不過(guò)以上的方式主要是針對(duì)位圖,如果是svg的圖片,則會(huì)稍微復(fù)雜一些,需要另行處理。

svg格式的判斷

svg格式圖片是矢量圖,對(duì)應(yīng)的數(shù)據(jù)一般使用 xml 標(biāo)記語(yǔ)言進(jìn)行描述,所以我們讀取到圖像數(shù)據(jù)后,需要對(duì)應(yīng)的標(biāo)識(shí)署名是 <svg,如果對(duì)應(yīng)的圖像數(shù)據(jù)中擁有該標(biāo)識(shí),則大致可以判定為svg格式的圖片。

<svg標(biāo)識(shí)有4個(gè)符號(hào)和字母,對(duì)應(yīng)的數(shù)值:60, 115, 118, 103,接下來(lái)我就需要判斷圖像文件是否有同樣的數(shù)據(jù)了。

imgUint8Array[0] === 60 && imgUint8Array[1] === 115 && imgUint8Array[3] === 118 && imgUint8Array[3] === 103 // svg 格式

以上代碼就是簡(jiǎn)單的判斷svg格式了。

但是,我們一般的svg圖片,圖像數(shù)據(jù)最開(kāi)始是包含有xml標(biāo)記語(yǔ)言的 <?xm 標(biāo)簽,這個(gè)時(shí)候我們根據(jù)格式再判斷:

if (isEqualFormatPrefix(fileUint8Array, [60, 63, 120, 109], offset)) { // 判斷是否以 <?xm 開(kāi)頭
  if (isHasSignCodes(fileUint8Array, [60, 115, 118, 103])) { // 判斷是否包含 <svg 標(biāo)簽
    return'svg'
  }
}

注意:以上針對(duì)svg格式矢量圖的這種判斷方式,是以 xml 標(biāo)記語(yǔ)言的標(biāo)簽符號(hào)進(jìn)行判斷的,只能處理通過(guò)更改后綴名的方式偽造的圖片文件。當(dāng)我們偽造一個(gè)假的文件,包含有 <svg 標(biāo)簽標(biāo)識(shí)時(shí),則可以逃避這種判斷。

總結(jié)

瀏覽器支持的圖片格式中,除了svg以外,其他幾種位圖格式,都可以較好的通過(guò)讀取圖像二進(jìn)制數(shù)據(jù)的方式判斷出圖片文件的真實(shí)格式,能夠防止文件偽造繞開(kāi)判斷,造成不必要的異常等問(wèn)題。

到此這篇關(guān)于JavaScript實(shí)現(xiàn)獲取圖片文件真實(shí)格式的示例代碼的文章就介紹到這了,更多相關(guān)JavaScript獲取圖片文件真實(shí)格式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JS實(shí)現(xiàn)的圖片預(yù)覽插件與用法示例【不上傳圖片】

    JS實(shí)現(xiàn)的圖片預(yù)覽插件與用法示例【不上傳圖片】

    這篇文章主要介紹了JS實(shí)現(xiàn)的圖片預(yù)覽插件與用法,基于自定義插件uploadPreview.js實(shí)現(xiàn)圖片的預(yù)覽功能,不需要進(jìn)行圖片的上傳,非常簡(jiǎn)便實(shí)用,需要的朋友可以參考下
    2016-11-11
  • 微信小程序日期時(shí)間選擇器使用方法

    微信小程序日期時(shí)間選擇器使用方法

    這篇文章主要為大家詳細(xì)介紹了微信小程序日期時(shí)間選擇器的使用方法,自定義精確到分秒或時(shí)段,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • webpack開(kāi)發(fā)跨域問(wèn)題解決辦法

    webpack開(kāi)發(fā)跨域問(wèn)題解決辦法

    本篇文章主要介紹了webpack開(kāi)發(fā)跨域問(wèn)題解決辦法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • 詳解cesium實(shí)現(xiàn)大批量POI點(diǎn)位聚合渲染優(yōu)化方案

    詳解cesium實(shí)現(xiàn)大批量POI點(diǎn)位聚合渲染優(yōu)化方案

    這篇文章主要為大家介紹了cesium實(shí)現(xiàn)大批量POI點(diǎn)位聚合渲染優(yōu)化方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • webpack HappyPack實(shí)戰(zhàn)詳解

    webpack HappyPack實(shí)戰(zhàn)詳解

    這篇文章主要介紹了webpack HappyPack實(shí)戰(zhàn)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • JavaScript模塊化開(kāi)發(fā)之SeaJS

    JavaScript模塊化開(kāi)發(fā)之SeaJS

    SeaJS是一個(gè)遵循CommonJS規(guī)范的JavaScript模塊加載框架,可以實(shí)現(xiàn)JavaScript的模塊化開(kāi)發(fā)及加載機(jī)制,本文給大家介紹JavaScript模塊化開(kāi)發(fā)之SeaJS,需要的朋友參考下
    2015-12-12
  • js定時(shí)器不準(zhǔn)確問(wèn)題的解決方法

    js定時(shí)器不準(zhǔn)確問(wèn)題的解決方法

    本文主要介紹了js定時(shí)器不準(zhǔn)確問(wèn)題的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • JS數(shù)組方法reduce的用法實(shí)例分析

    JS數(shù)組方法reduce的用法實(shí)例分析

    這篇文章主要介紹了JS數(shù)組方法reduce的用法,結(jié)合實(shí)例形式詳細(xì)分析了JS數(shù)組方法reduce的基本功能、使用方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下
    2020-03-03
  • 理解Javascript_09_Function與Object

    理解Javascript_09_Function與Object

    在《理解Javascript_08_函數(shù)對(duì)象》中講解了很多函數(shù)對(duì)象的問(wèn)題,同時(shí)也留下了許多疑問(wèn),今天讓我們來(lái)解答部分問(wèn)題。
    2010-10-10
  • 微信小程序開(kāi)發(fā)(一) 微信登錄流程詳解

    微信小程序開(kāi)發(fā)(一) 微信登錄流程詳解

    本篇文章主要介紹了微信小程序開(kāi)發(fā)(一) 微信登錄流程,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。
    2017-01-01

最新評(píng)論

丽水市| 沙田区| 兖州市| 昌宁县| 天门市| 剑阁县| 甘谷县| 鄂尔多斯市| 达拉特旗| 新巴尔虎右旗| 涪陵区| 营口市| 石河子市| 康平县| 高唐县| 灵寿县| 黄大仙区| 龙泉市| 临沂市| 新竹市| 乌审旗| 姜堰市| 邯郸县| 三台县| 麦盖提县| 麻阳| 唐海县| 革吉县| 枣强县| 新绛县| 襄汾县| 临西县| 乌拉特中旗| 台东县| 高清| 乡宁县| 奎屯市| 新河县| 青铜峡市| 玛纳斯县| 元朗区|