乐趣区

关于node.js:使用Nodejs打包下载文件

本文介绍一下应用 Node.js 的 fs 模块创立 zip 文件,须要借助 archiver 包。

后端创立归档文件

这个操作个别由前端发动,如下图所示:

把抉择中文件地址发送给后端,后端依据文件地址创立归档文件,最初把归档文件地址返回给前端实现下载。

// 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),
  });

当然,你也能够间接在这里把文件输送给前端下载,不过会让这个打包程序看起来不够纯正。

我的做法是再写一个独自用于下载的接口,供前端调用。

下一篇文章说一下 前端下载时可能遇到的问题。

退出移动版