成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

探索前端黑科技——通過png圖的rgba值緩存數據

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

[[171485]]

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

原理

我們知道,通過為靜態資源設置Cache-Control和Expires響應頭,可以迫使瀏覽器對其進行緩存。瀏覽器在向后臺發起請求的時候,會先在自身的緩存里面找,如果緩存里面沒有,才會繼續向服務器請求這個靜態資源。利用這一點,我們可以把一些需要被緩存的信息通過這個靜態資源緩存機制來進行儲存。

那么我們如何把信息寫入到靜態資源中呢?canvas提供了.getImageData()方法和.createImageData()方法,可以分別用于讀取和設置圖片的rgba值。所以我們可以利用這兩個API進行信息的讀寫操作。

接下來看原理圖:

 

 當靜態資源進入緩存,以后的任何對于該圖片的請求都會先查找本地緩存,也就是說信息其實已經以圖片的形式被緩存到本地了。

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

靜態服務器

我們使用node搭建一個簡單的靜態服務器:

  1. const fs = require('fs'
  2. const http = require('http'
  3. const url = require('url'
  4. const querystring = require('querystring'
  5. const util = require('util'
  6.  
  7. const server = http.createServer((req, res) => { 
  8.   let pathname = url.parse(req.url).pathname 
  9.   let realPath = 'assets' + pathname 
  10.   console.log(realPath) 
  11.   if (realPath !== 'assets/upload') { 
  12.      fs.readFile(realPath, "binary"function(err, file) { 
  13.       if (err) { 
  14.         res.writeHead(500, {'Content-Type''text/plain'}) 
  15.         res.end(err) 
  16.       } else { 
  17.         res.writeHead(200, { 
  18.           'Access-Control-Allow-Origin''*'
  19.           'Content-Type''image/png'
  20.           'ETag'"666666"
  21.           'Cache-Control''public, max-age=31536000'
  22.           'Expires''Mon, 07 Sep 2026 09:32:27 GMT' 
  23.         }) 
  24.         res.write(file, "binary"
  25.         res.end() 
  26.       } 
  27.    }) 
  28.   } else { 
  29.     let post = '' 
  30.     req.on('data', (chunk) => { 
  31.       post += chunk 
  32.     }) 
  33.     req.on('end', () => { 
  34.       post = querystring.parse(post) 
  35.       console.log(post.imgData) 
  36.       res.writeHead(200, { 
  37.         'Access-Control-Allow-Origin''*' 
  38.       }) 
  39.       let base64Data = post.imgData.replace(/^data:image\/\w+;base64,/, ""
  40.       let dataBuffer = new Buffer(base64Data, 'base64'
  41.       fs.writeFile('assets/out.png', dataBuffer, (err) => { 
  42.         if (err) { 
  43.           res.write(err) 
  44.           res.end() 
  45.         } 
  46.         res.write('OK'
  47.         res.end() 
  48.       }) 
  49.     }) 
  50.   } 
  51. }) 
  52.  
  53. server.listen(80) 
  54.  
  55. console.log('Listening on port: 80' 

這個靜態資源的功能很簡單,它提供了兩個功能:通過客戶端傳來的base64生成圖片并保存到服務器;設置圖片的緩存時間并發送到客戶端。

關鍵部分是設置響應頭:

  1. res.writeHead(200, { 
  2.   'Access-Control-Allow-Origin''*'
  3.   'Content-Type''image/png'
  4.   'ETag'"666666"
  5.   'Cache-Control''public, max-age=31536000'
  6.   'Expires''Mon, 07 Sep 2026 09:32:27 GMT' 
  7. })  

我們為這張圖片設置了一年的Content-Type和十年的Expires,理論上足夠長了。下面我們來進行客戶端的coding。

客戶端

  1. <!-- client.html --> 
  2.  
  3. <canvas id="canvas" width="8", height="1"></canvas>  

假設我們需要存儲的是32位的數據,所以我們為canvas設置寬度為8,高度為1。到底為什么32位數據對應長度為8,是因為每一個像素都有一個rgba,對應著red,green,blue和alpha4個數值,所以需要除以4。

  1. <!-- client.js --> 
  2.  
  3. let keyString = '01234567890123456789012345678901' 
  4.          
  5. let canvas = document.querySelector('#canvas'
  6. let ctx = canvas.getContext('2d'
  7.  
  8. let imgData = ctx.createImageData(8, 1) 
  9.  
  10. for (let i = 0; i < imgData.data.length; i += 4) { 
  11.     imgData.data[i + 0] = parseInt(keyString[i]) + 50 
  12.     imgData.data[i + 1] = parseInt(keyString[i + 1]) + 100 
  13.     imgData.data[i + 2] = parseInt(keyString[i + 2]) + 150 
  14.     imgData.data[i + 3] = parseInt(keyString[i + 3]) + 200 
  15.  
  16. ctx.putImageData(imgData, 0, 0)  

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

我們現在可以打印一下,看看這個imgData是什么:

  1. // console.log(imgData.data) 
  2.  
  3. [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] 

接下來,我們要把這個canvas編譯為一張圖片的base64并發送給服務器,同時接收服務器的響應,對圖片進行緩存:

  1. $.post('http://xx.xx.xx.xx:80/upload', { imgData: canvas.toDataURL() }, (data) => { 
  2.     if (data === 'OK') { 
  3.         let img = new Image() 
  4.         img.crossOrigin = "anonymous" 
  5.         img.src = 'http://xx.xx.xx.xx:80/out.png' 
  6.         img.onload = () => { 
  7.             console.log('完成圖片請求與緩存'
  8.             ctx.drawImage(img, 0, 0) 
  9.             console.log(ctx.getImageData(0, 0, 8, 1).data) 
  10.         } 
  11.     } 
  12. })  

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

結果分析

開啟服務器,運行客戶端,***次加載的時候通過控制臺可以看到響應的圖片信息:

 

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

關閉當前頁面,重新載入:

 

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

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

  1. 源數據:  [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] 
  2.  
  3. 緩存數據:[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]  

可以看到,源數據與緩存數據基本一致,在alpha值的誤差偏大,在rgb值內偶有誤差。通過分析,認為產生誤差的原因是服務端在進行base64轉buffer的過程中,所涉及的運算會導致數據的改變,這一點有待考證。

之前得到的結論,源數據與緩存數據存在誤差的原因,經查證后確定為alpha值的干擾所致。如果我們把alpha值直接定為255,并且只把數據存放在rgb值內部,即可消除誤差。下面是改良后的結果:

  1. 源數據: [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] 
  2.  
  3. 緩存數據:[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]  

因為我懶,只是把alpha值給定為255而沒有把循環賦值的邏輯進行更新,所以第4n位的元數據被直接替換成了255,這個留著讀者自行修改有空再改……

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

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

后記

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

責任編輯:龐桂玉 來源: segmentfault
相關推薦

2017-07-13 13:56:16

前端黑科技緩存數據

2024-03-18 08:33:16

2021-10-27 10:34:09

數據庫

2025-05-14 00:00:01

2015-10-21 13:38:28

2023-11-13 14:53:23

2023-04-07 08:43:47

Go語言應用場

2017-07-07 10:24:56

云計算

2018-07-23 06:38:40

AI芯片數據中心

2025-03-24 01:00:00

2019-11-07 11:40:12

大數據Kafka技術

2016-01-29 17:53:20

Taste?Analy大數據云計算

2023-11-11 19:43:12

緩存數據庫

2016-07-14 16:40:56

黑科技

2023-09-22 08:27:39

2017-10-13 15:30:10

網頁黑科技性能

2015-01-22 10:17:05

微軟win10

2021-11-27 07:09:39

P 圖工具工具應用軟件

2018-03-28 09:35:16

數據系統云服務
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久精品一区二区三区四季av | 国产sm主人调教女m视频 | 99免费看 | 一级黄色毛片免费 | 国产伦精品 | 日日摸日日添日日躁av | 国产精品久久久爽爽爽麻豆色哟哟 | 亚洲欧美一区二区三区国产精品 | 国产一区二区三区在线 | 国产激情精品一区二区三区 | 国产精品成人一区二区 | 日日夜夜天天 | 午夜影院在线观看视频 | 国产在线精品一区二区 | 午夜影院在线观看 | 亚洲日日操 | 中文精品久久 | 久久久久国色av免费观看性色 | 国产a区 | 国产精品久久欧美久久一区 | 色视频在线免费观看 | 久久91| 毛片在线免费播放 | 性福视频在线观看 | 日韩一区二区在线播放 | 中文字幕视频在线看5 | 美女啪啪国产 | 一区观看 | 亚洲欧美日韩精品久久亚洲区 | 91精品国产色综合久久不卡蜜臀 | 国产精品免费一区二区三区四区 | 天堂中文资源在线 | 91久久久久久久久久久久久 | 中文字幕一区在线 | 欧美在线小视频 | 欧美日韩大陆 | 欧美a v在线 | 久久久亚洲成人 | 91精品一区 | 欧美黄在线观看 | 欧美aⅴ|