00 学习路线与贯穿项目

1. 为什么文件处理比 CRUD 难

数据库 CRUD 通常由驱动管理连接和事务,文件流程却同时涉及路径、权限、磁盘空间、句柄、Stream、临时目录和操作系统差异。一次 Markdown ZIP 转换至少拥有三种资源:

输入 ZIP + 解压目录 + 输出 ZIP

任意阶段都可能失败,失败后还要回答:输出是否完整、句柄是否关闭、临时文件是否删除、客户端是否已经收到响应头。

2. 贯穿链路

HTTP 上传
  → Multer 临时文件
  → 创建任务目录
  → 校验 ZIP Entry
  → 解压 Markdown 和资源
  → 渲染并清理 HTML
  → Archiver 生成结果 ZIP
  → Stream 下载
  → 清理临时目录

各层职责:

主要职责
Express/Multer HTTP 输入、上传大小和数量限制
path 构造、解析和比较路径
fs 文件、目录和句柄操作
Stream 有界缓冲的数据传输
yauzl 读取 ZIP 目录和 Entry 数据
archiver 生成 ZIP
Service 状态、清理、错误映射和审计

3. 两套 Stream 不要混淆

本系列重点是 Node.js Stream:

import type { Readable, Writable } from "node:stream";

浏览器 Fetch 使用的通常是 Web Streams:

ReadableStream<Uint8Array>

Node.js 22 同时支持两套模型,也提供转换接口,但它们的事件和消费方式不同。本教程出现 dataendfinishpipe() 时,指 Node.js Stream。

4. 练习目录约定

建议单独创建:

playground/fs-path-stream/
├─input/
├─work/
└─output/

不要用真实上传目录练习删除。每个练习都应先打印将要操作的绝对路径。

5. 错误分类

贯穿系列使用三类错误:

用户数据错误:非法 ZIP、路径穿越、文件过大
环境错误:权限不足、磁盘满、句柄耗尽
程序错误:重复回调、遗漏 await、错误事件未监听

公开响应不应暴露服务器绝对路径;日志可以保存 taskId、相对路径、错误码和阶段。

6. 每章验收方式

除了正常输入,还要测试:

练习题

  1. 画出当前 Markdown ZIP 接口中所有临时文件的生命周期。
  2. 标出每一步可能占用的句柄、内存和磁盘空间。
  3. 解释为什么 HTTP 超时不能自动停止后台文件写入。
  4. 给用户输入错误和系统错误分别设计三个业务码。

完成标准