Rumah >hujung hadapan web >tutorial js >Mari kita bincangkan tentang cara menggunakan Node untuk mencapai pemampatan kandungan melalui latihan
Bagaimana untuk mencapai pemampatan kandungan menggunakan Nodejs? Artikel berikut akan bercakap tentang kaedah melaksanakan pemampatan kandungan (gzip/br/deflate) di bahagian Node melalui amalan saya harap ia akan membantu anda!
Apabila menyemak log aplikasi saya, saya mendapati ia sentiasa mengambil masa beberapa saat untuk dimuatkan selepas memasuki halaman log (antara muka tidak penomboran). Jadi saya membuka panel rangkaian dan menyemak
hanya untuk mendapati bahawa data yang dikembalikan oleh antara muka tidak dimampatkan menyangka antara muka menggunakan proksi terbalik Nginx , Nginx secara automatik akan membantu saya melakukan lapisan ini (saya akan meneroka ini kemudian, secara teorinya boleh dilaksanakan)
Ujung belakang di sini ialah perkhidmatan Node >
Artikel ini adalah Kongsi pengetahuan berkaitan dan prapengetahuan dalam HTTP数据压缩
Node侧的实践
Pelanggan berikut semuanya merujuk kepada penyemak imbaspengekodan terima Apabila klien memulakan permintaan ke pelayan, ia akan menambah medan
dalam pengepala permintaan dan nilainya menunjukkan klien accept-encoding
format支持的压缩内容编码
pada respons pengepala. Kandungan bekas content-encoding
实际压缩使用的编码算法
ialah algoritma pemampatan data tanpa kehilangan yang menggunakan kedua-dua algoritma deflate
dan LZ77
. 哈夫曼编码(Huffman Coding)
ialah algoritma berdasarkan gzip
DEFLATE
merujuk kepada br
Format data ini direka untuk meningkatkan lagi nisbah mampatan dan boleh memampatkan teks secara relatif Brotli
Tingkatkan ketumpatan mampatan deflate
, manakala kelajuan mampatan dan penyahmampatannya kekal hampir tidak berubah20%
, yang menyediakan penggunaan zlib 模块
, dan Gzip
Deflate/Inflate
Brotli
Di sini kami mengambil
dan gzip
digunakan dengan cara yang sama , tetapi API berbezaDeflate/Inflate
Brotli
stream
buffer
Memperkenalkan beberapa modul yang diperlukan
Menyahkod/memampatkan failconst zlib = require('zlib') const fs = require('fs') const stream = require('stream') const testFile = 'tests/origin.log' const targetFile = `${testFile}.gz` const decodeFile = `${testFile}.un.gz`
du
# 执行 du -ah tests # 结果如下 108K tests/origin.log.gz 2.2M tests/origin.log 2.2M tests/origin.log.un.gz 4.6M testsoperasi
流(stream)
menggunakan createGzip
createUnzip
zlib
Oleh itu, kod mampatan dan penyahmampatan dalam contoh berikut hendaklah dilaksanakan secara berasingan, jika tidak, ralat akan dilaporkan Terus gunakan kaedah pada contoh untuk lulus strim pipe
// 压缩 const readStream = fs.createReadStream(testFile) const writeStream = fs.createWriteStream(targetFile) readStream.pipe(zlib.createGzip()).pipe(writeStream) // 解压 const readStream = fs.createReadStream(targetFile) const writeStream = fs.createWriteStream(decodeFile) readStream.pipe(zlib.createUnzip()).pipe(writeStream)Kaedah 2 :
Gunakan pada , anda boleh melakukan pemprosesan lain secara berasingan dalam panggilan balik stream
pipeline
// 压缩 const readStream = fs.createReadStream(testFile) const writeStream = fs.createWriteStream(targetFile) stream.pipeline(readStream, zlib.createGzip(), writeStream, err => { if (err) { console.error(err); } }) // 解压 const readStream = fs.createReadStream(targetFile) const writeStream = fs.createWriteStream(decodeFile) stream.pipeline(readStream, zlib.createUnzip(), writeStream, err => { if (err) { console.error(err); } })Kaedah 3:
Promise kaedah pipeline
const { promisify } = require('util') const pipeline = promisify(stream.pipeline) // 压缩 const readStream = fs.createReadStream(testFile) const writeStream = fs.createWriteStream(targetFile) pipeline(readStream, zlib.createGzip(), writeStream) .catch(err => { console.error(err); }) // 解压 const readStream = fs.createReadStream(targetFile) const writeStream = fs.createWriteStream(decodeFile) pipeline(readStream, zlib.createUnzip(), writeStream) .catch(err => { console.error(err); })
Buffer
Menggunakan API, kedua-dua kaedah ini termasuk gzip
dan unzip
jenis 同步
异步
gzip
gzipSync
unzip
unzipSync
Tukar kepada , dan kemudian lakukan operasi selanjutnya readStream
Buffer
// 压缩 const buff = [] readStream.on('data', (chunk) => { buff.push(chunk) }) readStream.on('end', () => { zlib.gzip(Buffer.concat(buff), targetFile, (err, resBuff) => { if(err){ console.error(err); process.exit() } fs.writeFileSync(targetFile,resBuff) }) })gzipSync: Segerakkan
// 压缩 const buff = [] readStream.on('data', (chunk) => { buff.push(chunk) }) readStream.on('end', () => { fs.writeFileSync(targetFile,zlib.gzipSync(Buffer.concat(buff))) })Kaedah 2:
Baca terus readFileSync
penyahmampatan /mampatan kandungan teks melalui
// 压缩 const readBuffer = fs.readFileSync(testFile) const decodeBuffer = zlib.gzipSync(readBuffer) fs.writeFileSync(targetFile,decodeBuffer) // 解压 const readBuffer = fs.readFileSync(targetFile) const decodeBuffer = zlib.gzipSync(decodeFile) fs.writeFileSync(targetFile,decodeBuffer)Selain pemampatan fail, kadangkala ia mungkin perlu untuk menyahmampatkan kandungan yang dipindahkan secara langsung
这里以压缩文本内容为例
// 测试数据 const testData = fs.readFileSync(testFile, { encoding: 'utf-8' })
流(stream)
操作这块就考虑 string
=> buffer
=> stream
的转换就行
string
=> buffer
const buffer = Buffer.from(testData)
buffer
=> stream
const transformStream = new stream.PassThrough() transformStream.write(buffer) // or const transformStream = new stream.Duplex() transformStream.push(Buffer.from(testData)) transformStream.push(null)
这里以写入到文件示例,当然也可以写到其它的流里,如HTTP的Response
(后面会单独介绍)
transformStream .pipe(zlib.createGzip()) .pipe(fs.createWriteStream(targetFile))
Buffer
操作同样利用Buffer.from
将字符串转buffer
const buffer = Buffer.from(testData)
然后直接使用同步API进行转换,这里result就是压缩后的内容
const result = zlib.gzipSync(buffer)
可以写入文件,在HTTP Server
中也可直接对压缩后的内容进行返回
fs.writeFileSync(targetFile, result)
这里直接使用Node中 http
模块创建一个简单的 Server 进行演示
在其他的 Node Web
框架中,处理思路类似,当然一般也有现成的插件,一键接入
const http = require('http') const { PassThrough, pipeline } = require('stream') const zlib = require('zlib') // 测试数据 const testTxt = '测试数据123'.repeat(1000) const app = http.createServer((req, res) => { const { url } = req // 读取支持的压缩算法 const acceptEncoding = req.headers['accept-encoding'].match(/(br|deflate|gzip)/g) // 默认响应的数据类型 res.setHeader('Content-Type', 'application/json; charset=utf-8') // 几个示例的路由 const routes = [ ['/gzip', () => { if (acceptEncoding.includes('gzip')) { res.setHeader('content-encoding', 'gzip') // 使用同步API直接压缩文本内容 res.end(zlib.gzipSync(Buffer.from(testTxt))) return } res.end(testTxt) }], ['/deflate', () => { if (acceptEncoding.includes('deflate')) { res.setHeader('content-encoding', 'deflate') // 基于流的单次操作 const originStream = new PassThrough() originStream.write(Buffer.from(testTxt)) originStream.pipe(zlib.createDeflate()).pipe(res) originStream.end() return } res.end(testTxt) }], ['/br', () => { if (acceptEncoding.includes('br')) { res.setHeader('content-encoding', 'br') res.setHeader('Content-Type', 'text/html; charset=utf-8') // 基于流的多次写操作 const originStream = new PassThrough() pipeline(originStream, zlib.createBrotliCompress(), res, (err) => { if (err) { console.error(err); } }) originStream.write(Buffer.from('<h1>BrotliCompress</h1>')) originStream.write(Buffer.from('<h2>测试数据</h2>')) originStream.write(Buffer.from(testTxt)) originStream.end() return } res.end(testTxt) }] ] const route = routes.find(v => url.startsWith(v[0])) if (route) { route[1]() return } // 兜底 res.setHeader('Content-Type', 'text/html; charset=utf-8') res.end(`<h1>404: ${url}</h1> <h2>已注册路由</h2> <ul> ${routes.map(r => `<li><a href="${r[0]}">${r[0]}</a></li>`).join('')} </ul> `) res.end() }) app.listen(3000)
更多node相关知识,请访问:nodejs 教程!
Atas ialah kandungan terperinci Mari kita bincangkan tentang cara menggunakan Node untuk mencapai pemampatan kandungan melalui latihan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!