Node.js如何通过流而非磁盘实现文件夹复制与压缩?
问题与解决方案:Netlify函数无磁盘写入权限下的模板压缩返回
问题背景
原代码在本地可正常运行:读取/template目录,替换变量后写入/theme目录,再压缩该目录并通过HTTP返回。但部署到Netlify后失败,因为Netlify函数环境不允许磁盘写入操作。
解决方案思路
跳过磁盘写入步骤,全程在内存中完成模板变量替换与压缩:
- 遍历模板目录的所有文件
- 读取文件内容并替换变量
- 将处理后的内容直接添加到JSZip实例
- 生成zip文件并返回响应
修改后代码
const path = require("path"); const fs = require("fs").promises; const JSZip = require("JSZip"); const templateDir = path.join(__dirname, "template"); exports.handler = async (event, context) => { // 初始化变量,优先从查询参数获取 const vars = { theme_name: "Theme Name", theme_slug: "theme-slug", author_name: "Author Name", ...event.queryStringParameters }; // 遍历目录并处理文件,添加到zip const processDirectory = async (dir, zip, basePath = "") => { const entries = await fs.readdir(dir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(dir, entry.name); const zipPath = path.join(basePath, entry.name); if (entry.isDirectory()) { await processDirectory(fullPath, zip, zipPath); } else { // 读取文件内容并替换变量 let content = await fs.readFile(fullPath, "utf-8"); // 替换所有变量占位符,比如{{theme_name}} Object.keys(vars).forEach(key => { const placeholder = `{{${key}}}`; content = content.replace(new RegExp(placeholder, "g"), vars[key]); }); // 将处理后的内容添加到zip zip.file(zipPath, content); } } }; try { const zip = new JSZip(); await processDirectory(templateDir, zip); // 生成zip的base64格式内容 const zipBase64 = await zip.generateAsync({ type: "base64" }); return { statusCode: 200, body: zipBase64, headers: { "Content-Type": "application/zip", "Content-Disposition": "attachment; filename=theme.zip", "Content-Transfer-Encoding": "base64" } }; } catch (err) { return { statusCode: 500, body: JSON.stringify({ error: err.message }) }; } };
关键改动说明
- 移除磁盘写入依赖:不再使用
copy-template-dir写入本地目录,改为直接在内存中处理文件内容 - 异步文件操作:使用
fs.promises替代同步方法,符合Netlify函数的异步执行要求 - 变量替换逻辑:手动实现模板变量替换,兼容原代码的
{{变量名}}占位符格式 - 内存中压缩:处理后的文件直接加入JSZip,无需先写入磁盘再读取,完全规避磁盘权限问题
内容的提问来源于stack exchange,提问作者Joseph Farruggio
相关产品推荐
相关产品推荐

