九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
探索前端黑科技——通過 png 圖的 rgba 值緩存數(shù)據(jù)
作者:jrainlau

  鏈接:segmentfault.com/a/1190000006866207

  說起前端緩存,大部分人想到的無非是幾個(gè)常規(guī)的方案,比如cookie,localStorage,sessionStorage,或者加上indexedDB和webSQL,以及manifest離線緩存。除此之外,到底還有沒有別的方法可以進(jìn)行前端的數(shù)據(jù)緩存呢?這篇文章將會帶你一起來探索,如何一步一步地通過png圖的rgba值來緩存數(shù)據(jù)的黑科技之旅。

  原理

  我們知道,通過為靜態(tài)資源設(shè)置Cache-Control和Expires響應(yīng)頭,可以迫使瀏覽器對其進(jìn)行緩存。瀏覽器在向后臺發(fā)起請求的時(shí)候,會先在自身的緩存里面找,如果緩存里面沒有,才會繼續(xù)向服務(wù)器請求這個(gè)靜態(tài)資源。利用這一點(diǎn),我們可以把一些需要被緩存的信息通過這個(gè)靜態(tài)資源緩存機(jī)制來進(jìn)行儲存。

  那么我們?nèi)绾伟研畔懭氲届o態(tài)資源中呢?canvas提供了.getImageData()方法和.createImageData()方法,可以分別用于讀取和設(shè)置圖片的rgba值。所以我們可以利用這兩個(gè)API進(jìn)行信息的讀寫操作。

  接下來看原理圖:


  當(dāng)靜態(tài)資源進(jìn)入緩存,以后的任何對于該圖片的請求都會先查找本地緩存,也就是說信息其實(shí)已經(jīng)以圖片的形式被緩存到本地了。

  注意,由于rgba值只能是[0, 255]之間的整數(shù),所以本文所討論的方法僅適用于純數(shù)字組成的數(shù)據(jù)。

  靜態(tài)服務(wù)器

  我們使用node搭建一個(gè)簡單的靜態(tài)服務(wù)器:

  const fs = require('fs')

  const http = require('http')

  const url = require('url')

  const querystring = require('querystring')

  const util = require('util')

  const server = http.createServer((req, res) => {

  let pathname = url.parse(req.url).pathname

  let realPath = 'assets' + pathname

  console.log(realPath)

  if (realPath !== 'assets/upload') {

  fs.readFile(realPath, 'binary', function(err, file) {

  if (err) {

  res.writeHead(500, {'Content-Type': 'text/plain'})

  res.end(err)

  } else {

  res.writeHead(200, {

  'Access-Control-Allow-Origin': '*',

  'Content-Type': 'image/png',

  'ETag': '666666',

  'Cache-Control': 'public, max-age=31536000',

  'Expires': 'Mon, 07 Sep 2026 09:32:27 GMT'

  })

  res.write(file, 'binary')

  res.end()

  }

  })

  } else {

  let post = ''

  req.on('data', (chunk) => {

  post += chunk

  })

  req.on('end', () => {

  post = querystring.parse(post)

  console.log(post.imgData)

  res.writeHead(200, {

  'Access-Control-Allow-Origin': '*'

  })

  let base64Data = post.imgData.replace(/^data:image\/\w+;base64,/, '')

  let dataBuffer = new Buffer(base64Data, 'base64')

  fs.writeFile('assets/out.png', dataBuffer, (err) => {

  if (err) {

  res.write(err)

  res.end()

  }

  res.write('OK')

  res.end()

  })

  })

  }

  })

  server.listen(80)

  console.log('Listening on port: 80')

  這個(gè)靜態(tài)資源的功能很簡單,它提供了兩個(gè)功能:通過客戶端傳來的base64生成圖片并保存到服務(wù)器;設(shè)置圖片的緩存時(shí)間并發(fā)送到客戶端。

  關(guān)鍵部分是設(shè)置響應(yīng)頭:

  res.writeHead(200, {

  'Access-Control-Allow-Origin': '*',

  'Content-Type': 'image/png',

  'ETag': '666666',

  'Cache-Control': 'public, max-age=31536000',

  'Expires': 'Mon, 07 Sep 2026 09:32:27 GMT'

  })

  我們?yōu)檫@張圖片設(shè)置了一年的Content-Type和十年的Expires,理論上足夠長了。下面我們來進(jìn)行客戶端的coding。

  客戶端

  id='canvas' width='8', height='1'>

  假設(shè)我們需要存儲的是32位的數(shù)據(jù),所以我們?yōu)閏anvas設(shè)置寬度為8,高度為1。到底為什么32位數(shù)據(jù)對應(yīng)長度為8,是因?yàn)槊恳粋€(gè)像素都有一個(gè)rgba,對應(yīng)著red,green,blue和alpha4個(gè)數(shù)值,所以需要除以4。

  let keyString = '01234567890123456789012345678901'

  let canvas = document.querySelector('#canvas')

  let ctx = canvas.getContext('2d')

  let imgData = ctx.createImageData(8, 1)

  for (let i = 0; i imgData.data.length; i += 4) {

  imgData.data[i + 0] = parseInt(keyString[i]) + 50

  imgData.data[i + 1] = parseInt(keyString[i + 1]) + 100

  imgData.data[i + 2] = parseInt(keyString[i + 2]) + 150

  imgData.data[i + 3] = parseInt(keyString[i + 3]) + 200

  }

  ctx.putImageData(imgData, 0, 0)

  首先我們假設(shè)需要被緩存的字符串為32位的01234567890123456789012345678901,然后我們使用.createImageData(8, 1)生成一個(gè)空白的imgData對象。接下來,我們對這個(gè)空對象進(jìn)行賦值。為了實(shí)驗(yàn)效果更加直觀,我們對rgba值都進(jìn)行了放大。設(shè)置完了imgData以后,通過.putImageData()方法把它放入我們的canvas即可。

  我們現(xiàn)在可以打印一下,看看這個(gè)imgData是什么:

  // console.log(imgData.data)

  [50, 101, 152, 203, 54, 105, 156, 207, 58, 109, 150, 201, 52, 103, 154, 205, 56, 107, 158, 209, 50, 101, 152, 203, 54, 105, 156, 207, 58, 109, 150, 201]

  接下來,我們要把這個(gè)canvas編譯為一張圖片的base64并發(fā)送給服務(wù)器,同時(shí)接收服務(wù)器的響應(yīng),對圖片進(jìn)行緩存:

  $.post('http://xx.xx.xx.xx:80/upload', { imgData: canvas.toDataURL() }, (data) => {

  if (data === 'OK') {

  let img = new Image()

  img.crossOrigin = 'anonymous'

  img.src = 'http://xx.xx.xx.xx:80/out.png'

  img.onload = () => {

  console.log('完成圖片請求與緩存')

  ctx.drawImage(img, 0, 0)

  console.log(ctx.getImageData(0, 0, 8, 1).data)

  }

  }

  })

  代碼很簡單,通過.toDataURL()方法把base64發(fā)送到服務(wù)器,服務(wù)器處理后生成圖片并返回,其圖片資源地址為http://xx.xx.xx.xx:80/out.png。在img.onload后,其實(shí)圖片就已經(jīng)完成了本地緩存了,我們在這個(gè)事件當(dāng)中把圖片信息打印出來,作為和源數(shù)據(jù)的對比。

  結(jié)果分析

  開啟服務(wù)器,運(yùn)行客戶端,第一次加載的時(shí)候通過控制臺可以看到響應(yīng)的圖片信息:


  200 OK,證明是從服務(wù)端獲取的圖片。

  關(guān)閉當(dāng)前頁面,重新載入:


  200 OK (from cache),證明是從本地緩存讀取的圖片。

  接下來直接看rgba值的對比:

  源數(shù)據(jù): [50, 101, 152, 203, 54, 105, 156, 207, 58, 109, 150, 201, 52, 103, 154, 205, 56, 107, 158, 209, 50, 101, 152, 203, 54, 105, 156, 207, 58, 109, 150, 201]

  緩存數(shù)據(jù):[50, 100, 152, 245, 54, 105, 157, 246, 57, 109, 149, 244, 52, 103, 154, 245, 56, 107, 157, 247, 50, 100, 152, 245, 54, 105, 157, 246, 57, 109, 149, 244]

  之前得到的結(jié)論,源數(shù)據(jù)與緩存數(shù)據(jù)存在誤差的原因,經(jīng)查證后確定為alpha值的干擾所致。如果我們把a(bǔ)lpha值直接定為255,并且只把數(shù)據(jù)存放在rgb值內(nèi)部,即可消除誤差。下面是改良后的結(jié)果:

  源數(shù)據(jù): [0, 1, 2, 255, 4, 5, 6, 255, 8, 9, 0, 255, 2, 3, 4, 255, 6, 7, 8, 255, 0, 1, 2, 255, 4, 5, 6, 255, 8, 9, 0, 255]

  緩存數(shù)據(jù):[0, 1, 2, 255, 4, 5, 6, 255, 8, 9, 0, 255, 2, 3, 4, 255, 6, 7, 8, 255, 0, 1, 2, 255, 4, 5, 6, 255, 8, 9, 0, 255]

  因?yàn)槲覒?,只是把a(bǔ)lpha值給定為255而沒有把循環(huán)賦值的邏輯進(jìn)行更新,所以第4n位的元數(shù)據(jù)被直接替換成了255,這個(gè)留著讀者自行修改有空再改……

  綜上所述,這個(gè)利用png圖的rgba值緩存數(shù)據(jù)的黑科技,在理論上是可行的,但是在實(shí)際操作過程中可能還要考慮更多的影響因素,比如設(shè)法消除服務(wù)端的誤差,采取容錯(cuò)機(jī)制等。實(shí)際上也是可行的。

  值得注意的是,localhost可能默認(rèn)會直接通過本地而不是服務(wù)器請求資源,所以在本地實(shí)驗(yàn)中,可以通過設(shè)置header進(jìn)行cors跨域,并且通過設(shè)置IP地址和80端口模擬服務(wù)器訪問。

  后記

  說是黑科技,其實(shí)原理非常簡單,與之類似的還有通過Etag等方法進(jìn)行強(qiáng)緩存。研究的目的僅僅為了學(xué)習(xí),千萬不要作為非法之用。如果讀者們發(fā)現(xiàn)這篇文章有什么錯(cuò)漏之處,歡迎指正,也希望有興趣的朋友可以一起進(jìn)行討論。

  關(guān)注「前端大全」

  看更多精選前端技術(shù)文章

  ↓↓↓
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
canvas 2 image的使用小心得
前端Base64編碼知識,一文打盡
使用nodejs將html5 canvas base64編碼圖片保存為文件
如何使用HTML5實(shí)現(xiàn)利用攝像頭拍照上傳功能
揭開QQ縮略圖與大圖不同背后的秘密(附簡單合成工具) | 小深刻的秋鼠
JS閃電打字特效
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服