【发布时间】:2013-12-22 21:18:51
【问题描述】:
我在 IIS7 上运行系统。页面 META 标记的编码为 UTF-8,根据 Chrome 菜单,实际编码看起来是相同的。
当我上传文件名中带有“长连字符”(“–”)的文件时,它会被转换为垃圾字符(“–”)。
垃圾字符保存在MySQL中,服务器上文件的文件名也有垃圾字符。但是,当我从数据库中提取文件名并使用 PHP 显示时,它会显示正确的连字符。
有没有办法将文件名存储为 UTF-8?当我尝试这段代码时,我得到一个错误:
$fn = iconv("CP-1252", "UTF-8", $file['name']);
debug($fn);
Notice (8): iconv(): Wrong charset, conversion from `CP-1252' to `UTF-8' is not allowed
--
几个月后更新! 所以这个问题与Windows上的一个PHP bug有关:http://bugs.php.net/bug.php?id=47096
Unicode 字符在 move_upload_file 上被 PHP 破坏 - 尽管我也看到了 rename 和 ZipArchive 的问题,所以我认为这是 PHP 和 Windows 的普遍问题。
我已经从 Wordpress 中找到了 here 的解决方法。我必须使用损坏的文件名存储文件,然后在下载/电子邮件/显示上对其进行清理。
以下是我正在使用的改编方法,以防将来对某人有用。如果您在下载/发送电子邮件之前尝试压缩文件,或者您需要将文件写入网络共享,这仍然没有多大用处。
public static function sanitizeFilename($filename, $utf8 = true)
{
if ( self::seems_utf8($filename) == $utf8 )
return $filename;
// On Windows platforms, PHP will mangle non-ASCII characters, see http://bugs.php.net/bug.php?id=47096
if ( 'WIN' == substr( PHP_OS, 0, 3 ) ) {
if(setlocale( LC_CTYPE, 0 )=='C'){ // Locale has not been set and the default is being used, according to answer by Colin Morelli at http://stackoverflow.com/questions/13788415/how-to-retrieve-the-current-windows-codepage-in-php
// thus, we force the locale to be explicitly set to the default system locale
$codepage = 'Windows-' . trim( strstr( setlocale( LC_CTYPE, '' ), '.' ), '.' );
}
else {
$codepage = 'Windows-' . trim( strstr( setlocale( LC_CTYPE, 0 ), '.' ), '.' );
}
$charset = 'UTF-8';
if ( function_exists( 'iconv' ) ) {
if ( false == $utf8 ){
$filename = iconv( $charset, $codepage . '//IGNORE', $filename );
}
else {
$filename = iconv( $codepage, $charset, $filename );
}
} elseif ( function_exists( 'mb_convert_encoding' ) ) {
if ( false == $utf8 )
$filename = mb_convert_encoding( $filename, $codepage, $charset );
else
$filename = mb_convert_encoding( $filename, $charset, $codepage );
}
}
return $filename;
}
public static function seems_utf8($str) {
$length = strlen($str);
for ($i=0; $i < $length; $i++) {
$c = ord($str[$i]);
if ($c < 0x80) $n = 0; # 0bbbbbbb
elseif (($c & 0xE0) == 0xC0) $n=1; # 110bbbbb
elseif (($c & 0xF0) == 0xE0) $n=2; # 1110bbbb
elseif (($c & 0xF8) == 0xF0) $n=3; # 11110bbb
elseif (($c & 0xFC) == 0xF8) $n=4; # 111110bb
elseif (($c & 0xFE) == 0xFC) $n=5; # 1111110b
else return false; # Does not match any model
for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
if ((++$i == $length) || ((ord($str[$i]) & 0xC0) != 0x80))
return false;
}
}
return true;
}
【问题讨论】:
标签: php cakephp encoding iis-7 utf-8