PHP 和 Linux utf-8 文件系统名称
PHP and Linux filesystem names in utf-8
我为 Windows 机器人找到了很多关于此的答案,对 Linux 没有什么有用的,我还没有检查过。
我的服务器是CentOS6,ext4文件系统,PHP版本是5.4.39,MySQL5.5.42.
全部设置为使用UTF8,从LANG环境变量到数据库,mysql客户端连接,php等
但是使用下面的代码我无法读取带有 èàòì 等特殊字符的文件
相同的代码适用于我的 Mac(php 和 mysql 从 ports 安装)。
正如您在代码中看到的那样,有一些带注释的测试。
mb_detect_encoding($track,'auto') returns UTF-8.
$db->bind("id",$this->request->get(1));
$file = $db->row("select f.name from file f where f.id = :id and f.type = 'mp3';");
$track = realpath(__DIR__ . '/../') . $file['name'];
//$track = mb_convert_encoding(realpath(__DIR__ . '/../' . $file['name']), "UTF-8");
//$track = iconv('utf-8', 'cp1252', realpath(__DIR__ . '/../' . $file['name']));
//echo mb_detect_encoding($track,'auto');
if (file_exists($track)) {
header("Content-Transfer-Encoding: binary");
header("Content-Type: audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3");
header('Content-length: ' . filesize($track));
header('Cache-Control: no-cache');
readfile($track);
}
有什么建议吗?
更新
看起来这个问题与 php 和文件相关的函数有关,这些函数似乎不使用 UTF-8 和文件名.. 出于某种原因。
我使用了一个简单的 php 脚本和 shell 中的 运行 并且我有相同的行为甚至直接在 php 脚本中指定文件名(所以没有数据库涉及)。
PHP 设置:
$ php -i | grep UTF
default_charset => UTF-8 => UTF-8
LANG => en_US.UTF-8
LC_CTYPE => en_US.UTF-8
_SERVER["LANG"] => en_US.UTF-8
_SERVER["LC_CTYPE"] => en_US.UTF-8
$ php --version
PHP 5.4.39 (cli) (built: Mar 19 2015 06:25:23)
需要说明的是,这样的事情是行不通的:
$track = "/path/to/existsing/file/with/spechialchars";
echo "-> " .$track . "\n";
if (file_exists($track)) {
echo "OK " .$track . "\n";
}
要记住的重要一点是,在 Linux 中,文件名没有字符编码,而只是一个 8 位字符串。
例如,如果您通过FTP上传文件,而FTP服务器使用Windows-1252字符编码,则文件名将为8位Windows-1252 .尝试使用 UTF-8 字符打开文件将失败,无论区域设置或 LANG 是什么。
这不同于 OS X,其中文件名始终为 UTF-8,而 Windows 其中文件名始终为 UTF-16。
您可能会发现 PHP 中的字符串也只是 8 位字符串,因此无法确定字符串使用的是什么编码 - 您可以轻松地将两个字符串编码为不同的字符集。
我的建议是确保您知道您读取或输出的任何字符串的编码,包括表单字段和文件名。
因此,请确保磁盘上的文件名是 UTF-8,并且您输入数据库的文件名值是 UTF-8。然后,当您从数据库中提取值时,文件变量应该已经是 UTF-8 编码的,并准备好传递给 fopen
命令。
我为 Windows 机器人找到了很多关于此的答案,对 Linux 没有什么有用的,我还没有检查过。
我的服务器是CentOS6,ext4文件系统,PHP版本是5.4.39,MySQL5.5.42.
全部设置为使用UTF8,从LANG环境变量到数据库,mysql客户端连接,php等
但是使用下面的代码我无法读取带有 èàòì 等特殊字符的文件
相同的代码适用于我的 Mac(php 和 mysql 从 ports 安装)。
正如您在代码中看到的那样,有一些带注释的测试。 mb_detect_encoding($track,'auto') returns UTF-8.
$db->bind("id",$this->request->get(1)); $file = $db->row("select f.name from file f where f.id = :id and f.type = 'mp3';"); $track = realpath(__DIR__ . '/../') . $file['name']; //$track = mb_convert_encoding(realpath(__DIR__ . '/../' . $file['name']), "UTF-8"); //$track = iconv('utf-8', 'cp1252', realpath(__DIR__ . '/../' . $file['name'])); //echo mb_detect_encoding($track,'auto'); if (file_exists($track)) { header("Content-Transfer-Encoding: binary"); header("Content-Type: audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3"); header('Content-length: ' . filesize($track)); header('Cache-Control: no-cache'); readfile($track); }
有什么建议吗?
更新
看起来这个问题与 php 和文件相关的函数有关,这些函数似乎不使用 UTF-8 和文件名.. 出于某种原因。
我使用了一个简单的 php 脚本和 shell 中的 运行 并且我有相同的行为甚至直接在 php 脚本中指定文件名(所以没有数据库涉及)。
PHP 设置:
$ php -i | grep UTF default_charset => UTF-8 => UTF-8 LANG => en_US.UTF-8 LC_CTYPE => en_US.UTF-8 _SERVER["LANG"] => en_US.UTF-8 _SERVER["LC_CTYPE"] => en_US.UTF-8 $ php --version PHP 5.4.39 (cli) (built: Mar 19 2015 06:25:23)
需要说明的是,这样的事情是行不通的:
$track = "/path/to/existsing/file/with/spechialchars"; echo "-> " .$track . "\n"; if (file_exists($track)) { echo "OK " .$track . "\n"; }
要记住的重要一点是,在 Linux 中,文件名没有字符编码,而只是一个 8 位字符串。
例如,如果您通过FTP上传文件,而FTP服务器使用Windows-1252字符编码,则文件名将为8位Windows-1252 .尝试使用 UTF-8 字符打开文件将失败,无论区域设置或 LANG 是什么。
这不同于 OS X,其中文件名始终为 UTF-8,而 Windows 其中文件名始终为 UTF-16。
您可能会发现 PHP 中的字符串也只是 8 位字符串,因此无法确定字符串使用的是什么编码 - 您可以轻松地将两个字符串编码为不同的字符集。
我的建议是确保您知道您读取或输出的任何字符串的编码,包括表单字段和文件名。
因此,请确保磁盘上的文件名是 UTF-8,并且您输入数据库的文件名值是 UTF-8。然后,当您从数据库中提取值时,文件变量应该已经是 UTF-8 编码的,并准备好传递给 fopen
命令。