如果服务器使用RethinkDB分布式数据库保存JSON数据,在保存的数据量持续增加的时候,网页端做数据查询操作时浏览器非常容易卡死,而且查询耗时,这个时候就需要另外考虑JSON数据的保存和读取,RethinkDB并不能满足需求。经过对比测试,JSON文本内容保存成txt文档之后,再压缩成zip文件占用空间非常小,可以作为优化方案来实施。
比如以JSON格式化方式保存成txt文档,文件大小是7.6MB,不做格式化保存文件大小是4MB,以压缩文件方式保存大小是175KB,不考虑格式化保存,压缩比是23.4倍。也就是保存1GB的JSON数据,只需要43.76MB的存储空间。来看下用JS方式保存和读取zip文件的具体代码逻辑实现。
一、Archiver方式保存zip实现
var fs = require('fs'); var archiver = require('archiver'); var filePath = "../xxxxxxx.zip"; var fileName = "xxxxxxx.txt"; var output = fs.createWriteStream(filePath); var archive = archiver('zip', { zlib: {level: 9}, forceLocalTime: true, }); archive.on('error', function (err) { console.log(err); }); archive.pipe(output); archive.append(jsonContent, {name: fileName}); archive.finalize();
filePath就是保存的zip压缩文件路径,fileName就是保存在zip压缩文件内的文件名,jsonContent就是要保存的JSON文本内容。
向压缩文件追加的内容也可以是一个Buffer、文件流或者目录:
// 追加一个文件流 archive.append(fs.createReadStream(__dirname + "/sourceFiles/1.txt"), { name: "file1.txt" }); // 追加一个string archive.append("string content!", { name: "file2.txt" }); // 追加一个buffer var buffer = Buffer.from("buff content!"); archive.append(buffer, { name: "file3.txt" }); // 追加一个现有文件 archive.file("sourceFiles/1.txt", { name: "file4.txt" }); // 追加一个目录(子目录也会被增加) archive.directory("sourceFiles/", "new-subdir"); // 追加一个目录——类似于直接复制 archive.directory("sourceFiles/"); // 将目标目录中的文件追加至根目录 archive.directory("sourceFiles/", false); // 新增空文件夹 archive.append('', { name: "empty-dir/" });
二、unzip方式获取压缩文件内容
如果只是解压文件到指定目录比较简单:
fs.createReadStream('path/to/archive.zip').pipe(unzip.Extract({ path: 'output/path' }));
但这边的需求不是解压文件,而是直接获取zip压缩文件里面的内容,这边用stream的Writable对象来获取写文件流里面的内容,在’finish’回调之后,拿到文件流完整内容。
如果不使用文件流数据,要调用entry.autodrain()释放内存,否则会耗尽服务器的内存。
var fs = require('fs'); var unzip = require("unzip"); var stream = require('stream'); var input = fs.createReadStream(".../archive.zip"); input.pipe(unzip.Parse()).on('entry', function (entry) {
var fileName = entry.path; var type = entry.type; // 'Directory' or 'File' var data = [];
if (fileName is target File you need) { var writeStream = new stream.Writable(); writeStream.writable = true; writeStream._write = (chunk, encoding, next) => { data.push(chunk); next() } writeStream.on('finish', () => { var content = Buffer.concat(data); }); entry.pipe(writeStream); } else { entry.autodrain(); } });
三、参考资料
node-unzip, node.js 跨平台使用流进行解压缩
Understanding Streams in Node.js
扩展阅读:
AngularJS集成HighCharts动态绘制CPU和内存变化曲线
转载请注明出处:陈文管的博客 – Node.js后端zip压缩文件保存和读取
扫码或搜索:文呓
微信公众号 扫一扫关注