圖片上傳與壓縮技巧總結(jié)

前端在項(xiàng)目開(kāi)發(fā)中缚态,會(huì)經(jīng)常遇到需要這樣的需求:
1.將用戶(hù)上傳的資料通過(guò)接口傳遞給后端
2.對(duì)于圖片類(lèi)型的資料,需要在前端進(jìn)行壓縮至200kb左右

難點(diǎn)1:
在開(kāi)發(fā)中,尤其是axios,默認(rèn)的傳參格式是josn摹察,而上傳文件的接口一般傳參格式都是form-data,在使用接口時(shí)倡鲸,參數(shù)在瀏覽器中的表現(xiàn)形式是這樣的:


image.png

難點(diǎn)2:
如何進(jìn)行圖片的壓縮


解決思路:
在封裝接口參數(shù)的時(shí)候供嚎,通過(guò)new FormData()創(chuàng)建實(shí)例,并通過(guò)append方法向?qū)嵗刑砑訉傩郧妥矗⑶沂謩?dòng)添加屬性cantentType

form_data.append('contentType', 'multipart/form-data')

axios攔截器請(qǐng)求攔截的時(shí)候加入對(duì)于contentType的識(shí)別克滴,并在contentType等于multipart/form-data的時(shí)候?qū)鲄⒏袷礁臑閙ultipart/form-data

// 請(qǐng)求攔截
service.interceptors.request.use((req) => {
  if (req.data.contentType === 'multipart/form-data') {
    req.headers['Content-Type'] = req.data.contentType
  }
}

對(duì)于需要傳遞給后端的圖片數(shù)據(jù),在前端我們進(jìn)行一個(gè)壓縮的處理优床,我將之封裝為了一個(gè)方法compressImg劝赔,代碼如下:

// 生成圖片對(duì)象
const readImg = (file) => {
  return new Promise((resolve, reject) => {
    const img = new Image()
    const reader = new FileReader()
    reader.onload = function (e) {
      // @ts-ignore
      img.src = e.target.result
    }
    reader.onerror = function (e) {
      reject(e)
    }
    reader.readAsDataURL(file)
    img.onload = function () {
      resolve(img)
    }
    img.onerror = function (e) {
      reject(e)
    }
  })
}

// 利用canvas壓縮圖片
export const compressImg = async (fileData, mx = 1000, mh = 1000) => {
  const canvasImgData = await readImg(fileData)
  return new Promise((resolve, reject) => {
    const canvas = document.createElement('canvas')
    const context = canvas.getContext('2d')
    // @ts-ignore
    const { width: originWidth, height: originHeight } = canvasImgData
    let dataURL = ''
    // 最大尺寸限制
    const maxWidth = mx
    const maxHeight = mh
    // 目標(biāo)尺寸
    let targetWidth = originWidth
    let targetHeight = originHeight
    if (originWidth > maxWidth || originHeight > maxHeight) {
      if (originWidth / originHeight > 1) {
        // 寬圖片
        targetWidth = maxWidth
        targetHeight = Math.round(maxWidth * (originHeight / originWidth))
      } else {
        // 高圖片
        targetHeight = maxHeight
        targetWidth = Math.round(maxHeight * (originWidth / originHeight))
      }
    }
    canvas.width = targetWidth
    canvas.height = targetHeight
    context.clearRect(0, 0, targetWidth, targetHeight)
    // 圖片繪制
    // @ts-ignore
    context.drawImage(canvasImgData, 0, 0, targetWidth, targetHeight)
    dataURL = canvas.toDataURL('image/jpeg') // 轉(zhuǎn)換圖片為dataURL
    resolve(dataURL)
    // 轉(zhuǎn)換為bolb對(duì)象
    // canvas.toBlob(function(blob) {
    //   resolve(blob)
    // }, type || 'image/png')
  })
}

用戶(hù)點(diǎn)擊頁(yè)面選擇圖片進(jìn)行本地上傳操作后,我們可以拿到對(duì)應(yīng)的數(shù)據(jù)胆敞,將這個(gè)數(shù)據(jù)作為參數(shù)傳遞給compressImg函數(shù)着帽,如果用的是vant的van-uploader組件杂伟,取:after-read="afterUploadRead"的第一個(gè)默認(rèn)參數(shù)file的file屬性

const afterUploadRead = (file, details) => {
  console.log(file.file)
}

如果是element的el-upload組件,則取得是:before-upload="beforeUpload"事件的默認(rèn)參數(shù)file

const beforeUpload = (file) => {
  console.log(file)
}

不管是何種情況仍翰,最終傳遞給compressImg方法的參數(shù)應(yīng)該是這樣的數(shù)據(jù)


image.png

上傳頁(yè)面壓縮圖片數(shù)據(jù)赫粥,封裝接口參數(shù)并觸發(fā)接口的代碼如下:

const finalCompressData = await compressImg(file.file)
let form_data = new FormData()
let fileName =
  file.file.name ||
  Math.floor(Math.random() * 100000) +
    '.' +
    file.content.split(';')[0].split('/')[1].replace('jpeg', 'jpg')
form_data.append('file', dataURLtoBlob(finalCompressData), fileName)
form_data.append('contentType', 'multipart/form-data')
uploadfile(form_data).then((res: any) => {
}

這樣壓縮后的圖片數(shù)據(jù),基本都只有100多kb予借,同時(shí)清晰度也是可以正常查看的越平。
注意,上面的這個(gè)compressImg函數(shù)只能壓縮圖片數(shù)據(jù)灵迫,其他格式的如視頻等秦叛,都是沒(méi)法壓縮的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末瀑粥,一起剝皮案震驚了整個(gè)濱河市挣跋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌利凑,老刑警劉巖浆劲,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異哀澈,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)度气,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)割按,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人磷籍,你說(shuō)我怎么就攤上這事适荣。” “怎么了院领?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵弛矛,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我比然,道長(zhǎng)丈氓,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任强法,我火速辦了婚禮万俗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘饮怯。我一直安慰自己闰歪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布蓖墅。 她就那樣靜靜地躺著库倘,像睡著了一般临扮。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上教翩,一...
    開(kāi)封第一講書(shū)人閱讀 49,111評(píng)論 1 285
  • 那天公条,我揣著相機(jī)與錄音,去河邊找鬼迂曲。 笑死靶橱,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的路捧。 我是一名探鬼主播关霸,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼杰扫!你這毒婦竟也來(lái)了队寇?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤章姓,失蹤者是張志新(化名)和其女友劉穎佳遣,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體凡伊,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡零渐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了系忙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片诵盼。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖银还,靈堂內(nèi)的尸體忽然破棺而出风宁,到底是詐尸還是另有隱情,我是刑警寧澤蛹疯,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布戒财,位于F島的核電站,受9級(jí)特大地震影響捺弦,放射性物質(zhì)發(fā)生泄漏饮寞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一羹呵、第九天 我趴在偏房一處隱蔽的房頂上張望骂际。 院中可真熱鬧,春花似錦冈欢、人聲如沸歉铝。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)太示。三九已至柠贤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間类缤,已是汗流浹背臼勉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留餐弱,地道東北人宴霸。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像膏蚓,于是被迫代替她去往敵國(guó)和親瓢谢。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容