早先的版本为了贯彻「不依赖第三方」,按 ZIP 规范手写了 Local File Header、Central Directory 与 CRC32 查表。7.1.0 把这段换掉了 —— 理由是系统本来就带压缩能力,自己维护一套格式实现没有收益,反而容易在中文文件名、大文件、目录递归这些边界上出问题。
调用方式
static string ApiZip(const string& body) {
string src = JsonValue(body, "src");
string dst = JsonValue(body, "dst");
if (src.empty() || dst.empty())
return "{\"ok\":false,\"message\":\"请选择源目录和输出 ZIP\"}";
if (dst.find(".zip") == string::npos) dst += ".zip";
string ps = "powershell -NoProfile -Command \"Compress-Archive -Path '"
+ src + "' -DestinationPath '" + dst + "' -Force\"";
string out;
if (RunCommand(Utf8ToWstr(ps), L"", out))
return "{\"ok\":true,\"path\":\"" + JsonEsc(dst) + "\"}";
return "{\"ok\":false,\"message\":\"打包失败:" + JsonEsc(out) + "\"}";
}| 开关 | 作用 |
|---|---|
-NoProfile | 不加载用户的 PowerShell 配置文件 —— 避免被自定义别名或代理设置干扰,也更快 |
-Force | 目标已存在时直接覆盖,不再弹交互确认 |
RunCommand | 复用第 04 章的管道封装,把 PowerShell 的报错原样带回界面 |
只挑部分文件打包
「另存为 ZIP」允许在源目录里选一部分文件打进去。文件名列表用 | 分隔传进来,逐个拼成 Compress-Archive -Path 的参数;一个都没选则用通配符打包整个目录:
while (q0 < fs.size()) { // fs 形如 "1.in|2.in|3.in"
size_t q1 = fs.find('|', q0);
string name = (q1 == string::npos) ? fs.substr(q0) : fs.substr(q0, q1 - q0);
if (!name.empty()) { hasFiles = true; items.push_back(wsDir + L"\\" + Utf8ToWstr(name)); }
if (q1 == string::npos) break;
q0 = q1 + 1;
}
if (!hasFiles) items.push_back(wsDir + L"\\*"); // 未指定:打包整个目录保存位置不再靠网页下载,而是弹出系统「另存为」对话框(GetSaveFileNameW + OFN_OVERWRITEPROMPT)让用户直接挑目录与文件名。用户点了取消,接口返回 {"ok":true,"cancel":true} 而不是当成错误 —— 取消是正常操作。