谁承认这种性格腐败?
Who recognizes this character corruption?
我有以下代码:
$files = ftp_nlist($conn_id, "/path/to/files");
$zip = new ZipArchive;
$res = $zip->open('filename.zip', ZipArchive::CREATE);
if ($res === TRUE) {
foreach ($files as $item) {
if ($item != '.' && $item != '..') {
// Get file contents
ob_start();
@ftp_get($conn_id, "php://output", "/path/to/files/{$item}", FTP_BINARY);
$data = ob_get_contents();
ob_end_clean();
$zip->addFromString($item, $data);
}
}
// ...
}
不幸的是,zip 文件中的文件名已损坏。例如,ßäÄçö.txt 变为 +ƒ+ñ+ä+º+¦.txt。
我假设这可以通过使用 iconv
来解决,但我找不到任何产生所需结果的编码对。据我所知,文件名存储为 UTF-8。当我不压缩文件而只是使用
下载它时
// ...
header("Content-Disposition: attachment; filename*=UTF-8''".rawurlencode($item));
//...
echo $data;
没有字符损坏。
UTF-8 中的“ßäÄçö”编码为 C3 9F C3 A4 C3 84 C3 A7 C3 B6
。如果将这些字节读取为 CP-437,则会得到“├ƒ├ñ├ä├º├╢”。如果您更改所有“├"s (C3
) to "+”(2B
)并将最后一个字符更改为“¦”,则会得到“+ƒ+ñ+ä+º+¦”。
我不知道为什么“├”变成了“+”,也不知道为什么“╢”变成了“¦”。我尝试在 Vim 中保存名为“├ƒ├ñ├ä├º├╢.txt”的文本文件,但它创建了一个名为“+ƒ+ñ+ä+º+¦.txt”的文件。但是当我在记事本中尝试同样的事情时,它创建了正确的文件名“├ƒ├ñ├ä├º├╢.txt”。因此,无论 Zip 文件中的字节发生什么,都与 Vim 所做的相同。
附录 D 中的 Zip File Format Specification 说文件名必须是 CP-437 或 UTF-8,因此您的文件名似乎在某处被视为 CP-437,加上任何其他步骤正在处理字节 C3
和 B6
。也许 PHP 的 ZipArchive 有解决方法,或者您可以使用其他 Zip 库。快速搜索 "php ziparchive utf-8" 找到了很多结果,但我没有立即看到解决方案。
我终于在用户贡献的笔记中找到了答案here:
Zip 规范似乎将 IBM437 指定为有效编码。
$encodedFilename = iconv('utf-8', 'IBM437', $filename);
$zip->addFromString($encodedFilename, 'foo');
解决问题。
我有以下代码:
$files = ftp_nlist($conn_id, "/path/to/files");
$zip = new ZipArchive;
$res = $zip->open('filename.zip', ZipArchive::CREATE);
if ($res === TRUE) {
foreach ($files as $item) {
if ($item != '.' && $item != '..') {
// Get file contents
ob_start();
@ftp_get($conn_id, "php://output", "/path/to/files/{$item}", FTP_BINARY);
$data = ob_get_contents();
ob_end_clean();
$zip->addFromString($item, $data);
}
}
// ...
}
不幸的是,zip 文件中的文件名已损坏。例如,ßäÄçö.txt 变为 +ƒ+ñ+ä+º+¦.txt。
我假设这可以通过使用 iconv
来解决,但我找不到任何产生所需结果的编码对。据我所知,文件名存储为 UTF-8。当我不压缩文件而只是使用
// ...
header("Content-Disposition: attachment; filename*=UTF-8''".rawurlencode($item));
//...
echo $data;
没有字符损坏。
UTF-8 中的“ßäÄçö”编码为 C3 9F C3 A4 C3 84 C3 A7 C3 B6
。如果将这些字节读取为 CP-437,则会得到“├ƒ├ñ├ä├º├╢”。如果您更改所有“├"s (C3
) to "+”(2B
)并将最后一个字符更改为“¦”,则会得到“+ƒ+ñ+ä+º+¦”。
我不知道为什么“├”变成了“+”,也不知道为什么“╢”变成了“¦”。我尝试在 Vim 中保存名为“├ƒ├ñ├ä├º├╢.txt”的文本文件,但它创建了一个名为“+ƒ+ñ+ä+º+¦.txt”的文件。但是当我在记事本中尝试同样的事情时,它创建了正确的文件名“├ƒ├ñ├ä├º├╢.txt”。因此,无论 Zip 文件中的字节发生什么,都与 Vim 所做的相同。
附录 D 中的 Zip File Format Specification 说文件名必须是 CP-437 或 UTF-8,因此您的文件名似乎在某处被视为 CP-437,加上任何其他步骤正在处理字节 C3
和 B6
。也许 PHP 的 ZipArchive 有解决方法,或者您可以使用其他 Zip 库。快速搜索 "php ziparchive utf-8" 找到了很多结果,但我没有立即看到解决方案。
我终于在用户贡献的笔记中找到了答案here:
Zip 规范似乎将 IBM437 指定为有效编码。
$encodedFilename = iconv('utf-8', 'IBM437', $filename);
$zip->addFromString($encodedFilename, 'foo');
解决问题。