使用Poco::zip添加目录/递归目录时持续抛出异常求助
解决Poco Zip添加目录时的"Illegal entry name"异常
嘿,我一眼就看出问题出在哪了——你调用addDirectory的时候传错参数啦!
你代码里这行:
c.addDirectory(targetDir, Poco::DateTime(Timestamp));// give exception
这里的targetDir是你要生成的ZIP文件的路径(比如./output.zip),但addDirectory需要的是压缩包内部的目录路径,不是外部的ZIP文件路径!Poco的ZipCommon::isValidPath校验会直接把这种外部路径判定为“包含父目录引用”,直接抛出异常。
下面给你一步步解决:
1. 修正目录添加的核心逻辑
其实你根本不需要手动调用addDirectory,addRecursive会自动帮你处理目录结构。把你的目录处理代码改成这样就行:
if (aFile.isDirectory()) { Poco::Path sourceDir(source); // 把源目录的内容递归添加到压缩包根目录 // 第二个参数是空字符串,表示压缩包内的根路径 // PRUNE_DIRECTORY选项会跳过源目录本身,只加里面的内容;如果想保留源目录作为顶层目录,去掉这个选项就行 c.addRecursive(sourceDir, "", Poco::Zip::Compress::PRUNE_DIRECTORY); }
2. 搞懂Poco的路径校验规则
Poco的isValidPath会拒绝以下几种路径,你以后写代码要注意:
- 绝对路径(比如Windows的
C:\test或者Linux的/home/test) - 包含
../(父目录引用)的路径 - 带非法字符的路径(比如Windows下的
:、*、?这些)
所以传给addDirectory、addFile的路径必须是压缩包内部的相对路径,不能用外部文件系统的绝对路径。
3. 完整修正后的代码示例
把你的核心代码替换后,大概是这样:
Poco::DateTime(Timestamp); std::set<std::string> extensionsSet; std::ofstream fos(target, std::ios::binary); Poco::Zip::Compress c(fos, true); // 处理需要存储的扩展名集合 for (int i = 0; i < extensions.Size(); i++) { std::string ext = std::dynamic_pointer_cast<String>(extensions.operator[](i))->GetPrimitive(); extensionsSet.insert(ext); } c.setStoreExtensions(extensionsSet); Poco::File aFile(source); if (aFile.exists()) { Poco::Path p(aFile.path()); if (aFile.isDirectory()) { Poco::Path sourceDir(source); // 递归添加目录内容到压缩包根目录 c.addRecursive(sourceDir, "", Poco::Zip::Compress::PRUNE_DIRECTORY); } else if (aFile.isFile()) { // 添加单个文件,用文件名作为压缩包内的路径 c.addFile(p, p.getFileName()); } } else { _log.EndMethod(); throw new Poco::FileNotFoundException("File Not Found"); } c.close(); // 必须调用这一步来完成ZIP文件的最终写入 fos.close();
额外小贴士
- 如果想把整个源目录作为压缩包内的一个子目录(比如把
/home/user/docs放到ZIP的my_docs/目录下),只需要把addRecursive的第二个参数改成"my_docs/"就行。 - 永远不要在压缩包内部路径里用绝对路径或者
../,严格遵守ZIP的路径规范,不然肯定会触发校验异常。
内容的提问来源于stack exchange,提问作者Tam Nguyen
相关产品推荐
相关产品推荐

