使用Node.js打包下载文件

本文介绍一下使用Node.js的fs模块创建zip文件,需要借助 archiver 包。
后端创建归档文件 这个操作一般由前端发起,如下图所示:
使用Node.js打包下载文件
文章图片

把选中的文件地址发送给后端,后端根据文件地址创建归档文件,最后把归档文件的地址返回给前端,完成下载。
// zip文件临时目录 const ZIP_TEMPORARY = path.resolve(__dirname, '../../static/zip'); /** * 文件归档 * @param opts 其中opts.targets就是所选文件的地址 type:Array */ m.zip = (opts) => { return new Promise((resolve, reject) => { if (!opts.targets || opts.targets?.length === 0) { reject({ success: false, msg: '参数错误' }); } const file_name = `/${new Date().getTime()}.zip`; const output = fs.createWriteStream(ZIP_TEMPORARY + file_name); const archive = archiver('zip', { zlib: { level: 9 }, // Sets the compression level. }); // 当所有文件都被打包完成会触发这个事件 output.on('close', () => { console.log(`${archive.pointer()} total bytes`); console.log('archiver has been finalized and the output file descriptor has closed.'); resolve({ success: true, hash: m.encode(ZIP_TEMPORARY + file_name), }); }); output.on('end', () => { console.log('Data has been drained'); }); // good practice to catch this error explicitly archive.on('error', (err) => { throw err; }); // 以管道的形式把文件输出到zip archive.pipe(output); // archive.directory 这个方法比较重要,它的作用是把子文件夹的文件也全部打包 opts.targets.forEach(async (item) => { const info = fs.lstatSync(item); if (info.isDirectory()) { archive.directory(item, item.split('/').pop(), null); } else { archive.file(item, { name: item.split('/').pop() }); } }); archive.finalize().then(); }); };

这样,程序执行后就可以在指定目录 生成一个按时间戳命名的.zip文件。
前端下载 上面的程序完成文件打包后,我们把.zip的地址返回给了前端:
resolve({ success: true, hash: m.encode(ZIP_TEMPORARY + file_name), });

当然,你也可以直接在这里把文件输送给前端下载,不过这会让打包程序看起来不够纯粹。
【使用Node.js打包下载文件】我的做法是再写一个单独用于下载的接口,供前端调用。
下一篇文章说一下 前端下载时可能遇到的问题。
Content-Disposition:attachment没有触发浏览器下载弹框

    推荐阅读