您當前的位置:首頁 > 攝影

上傳圖片,圖片太大,如何在前端實現圖片壓縮後上傳

作者:由 嘿-我的辣條 發表于 攝影時間:2021-09-16

上傳圖片是我們在前端開發中最常見不過的日常需求,當然了,為了提升使用者體驗,以及減少伺服器訪問圖片的壓力,一般情況在不影響圖片檢視的情況下,我們會對圖片進行適當的壓縮處理,處理後上傳,使用者的上傳操作的響應時間會大大減小,且在伺服器拿取圖片時,時間也會縮短。針對前端的壓縮最佳化,我下面寫了個簡版的壓縮處理。

function

compressPic

file

quality

{

let

reads

=

new

FileReader

();

reads

readAsDataURL

file

reads

onload

=

({

target

{

result

src

}})

{

// 這裡quality的範圍是(0-1)

var

canvas

=

document

createElement

“canvas”

);

var

ctx

=

canvas

getContext

“2d”

);

var

img

=

new

Image

();

img

src

=

src

img

onload

=

function

()

{

let

width

=

img

width

canvas

width

=

width

canvas

height

=

width

*

img

height

/

img

width

);

ctx

drawImage

img

0

0

canvas

width

canvas

height

);

// 轉換成base64格式 quality為圖片壓縮質量 0-1之間 值越小壓縮的越大 圖片質量越差

let

data

=

canvas

toDataURL

file

type

quality

);

return

data

}

};

},

透過上面這段程式碼即可實現圖片的壓縮處理,完成的實現思路就是:

input 讀取到 image/file 建立一個FileReader 使用 FileReader 將其轉換為 base64 編碼

new Image 建立img元素 使img的src指向FileReader轉換的base64

document。createElement(“canvas”) 建立canvas

ctx。drawImage(img,0,0, canvas。width, canvas。height) 將img畫到canvas上

canvas。toDataURL(file。type, quality) 將canvas轉換為圖片base64格式

透過上面的問題確實是能解決壓縮的問題 但是某些情況下 可能存在一些問題 quality的值存在0-1區間時 可能在測試0。1 至 0。99時 出現quality到0。8時或0。9時 壓縮後圖片記憶體卻佔的比之前更大了 在0。01 - 0。99這個區間內雖然是可以實現壓縮 但是壓縮的比例是不確定性的 所以我們在你實現壓縮為一定比例時 我們可以用另外一種發放去實現。

二分法實現:

具體的實現思路就是 就是我們先取quality為0。5 進行壓縮 壓縮後判斷圖片大小體積和指定體積比較 當壓縮後體積過小時 然後再二分取0。 5 - 1的一半 0。75 然後再去處理 體積大了 向下二分 體積小了 向上二分 ,但是要注意的一半取個3-4次二分即可 二分多次後會增長這個壓縮時間 影響使用者體驗, 具體的程式碼,如下:

function

compressPic

file

size

device

{

const

reader

=

new

FileReader

()

// 建立 FileReader

reader

readAsDataURL

file

reader

onload

=

({

target

{

result

src

}

})

=>

{

const

image

=

new

Image

()

// 建立 img 元素

image

src

=

src

const

canvas

=

document

createElement

‘canvas’

// 建立 canvas 元素

image

onload

=

()

=>

{

canvas

width

=

image

width

canvas

height

=

image

height

canvas

getContext

‘2d’

)。

drawImage

image

0

0

image

width

image

height

// 繪製 圖片到canvas上

let

canvasURL

nearFile

// 建立變數 圖片的file 最接近目標大小的file

let

pointDirection

=

true

// 設定預設的二分方向 true為加二分值 false為減二分值

let

quality

=

0

for

let

i

=

1

i

<=

device

i

++

{

canvasURL

=

canvas

toDataURL

file

type

pointDirection

quality

+=

1

/

2

**

i

))

quality

-=

1

/

2

**

i

)))

let

blob

=

dataURLtoBlob

canvasURL

// 此方法為base64轉化為blod方法 見上方

miniFile

=

blobToFile

blob

‘new’

+

file

name

file

type

// 此方法為blod轉file方法

// 上方呼叫的兩個方法 dataURLtoBlod和blobToFile已經更新到下方文章中 可拿來直接使用

}

return

miniFile

}

}

}

透過上面這段程式碼可以實現接近指定體積的壓縮,完整的實現思路就是:

input 讀取到 image/file 建立一個FileReader 使用 FileReader 將其轉換為 base64 編碼

new Image 建立img元素 使img的src指向FileReader轉換的base64

document。createElement(“canvas”) 建立canvas

ctx。drawImage(img,0,0, canvas。width, canvas。height) 將img畫到canvas上

建立幾個變數 canvasURL:canvas轉圖片的file;nearFile:二分後的file檔案

透過for迴圈 根據二分的次數 取到最接近的指定體積的quality的值

當然了 再很多情況中我們可能不一定給後端提供的是base64格式的圖片 我們上傳過去一般是file格式 在這我提供一個將base64轉為file格式的js方法

我們的實現思路就是 將base64轉化為blod格式 然後將其轉化為file格式

// base64轉換為blod

function

dataURLtoBlob

dataurl

{

var

arr

=

dataurl

split

‘,’

),

mime

=

arr

0

]。

match

/:(。*?);/

)[

1

],

bstr

=

atob

arr

1

]),

n

=

bstr

length

u8arr

=

new

Uint8Array

n

);

while

n

——

{

u8arr

n

=

bstr

charCodeAt

n

);

}

return

new

Blob

([

u8arr

],

{

type

mime

});

},

// blod轉化為file theBlod: blod格式檔案 fileName: 檔名稱 fileType:檔案型別

function

blobToFile

theBlob

fileName

fileType

{

let

file

=

new

window

File

([

theBlob

],

fileName

{

type

fileType

})

return

file

}

這裡我提供了一個demo可以供體驗者體驗下壓縮的功能

圖片壓縮demo

標簽: Canvas  file  img  壓縮  Quality