PHP 文件名(或其完整路径中的目录)可以包含 UTF-8 字符吗?

Posted

技术标签:

【中文标题】PHP 文件名(或其完整路径中的目录)可以包含 UTF-8 字符吗?【英文标题】:Can a PHP file name (or a dir in its full path) have UTF-8 characters? 【发布时间】:2010-10-17 00:28:15 【问题描述】:

我想访问一个名称中包含 UTF-8 字符的 php 文件。

文件中没有 BOM。它只包含一个显示几个 unicode 字符的 echo 语句。

从浏览器(FireFox 3.0.8、IE7)访问 PHP 页面会导致 HTTP 错误 500。

Apache日志中有两个条目(文件是/க.php;字母க是复合的,对应下面日志中的字符\xe0\xae\x95):

[Sat Apr 04 09:30:25 2009] [error] [client 127.0.0.1] PHP Warning: Unknown: failed to open stream: No such file or directory in Unknown on line 0

[2009 年 4 月 4 日星期六 09:30:25] [错误] [客户端 127.0.0.1] PHP 致命错误:未知:打开失败需要 'D:/va/ROOT/\xe0\xae\x95.php' ( include_path='.;C:\php5\pear') 在第 0 行的未知中

当文件名和目录名是英文时,相同的页面可以工作。在相同的设置中,对这些页面使用 SSI 没有问题。

编辑

删除了有关 url 重写的信息,因为它似乎不是一个因素。

移除 mod_rewrite 后,PHP 文件仍然无法工作。如果文件重命名为非 UTF 名称,则有效。但是,shtml 甚至可以在文件和/或路径名中使用 UTF 字符。

【问题讨论】:

【参考方案1】:

仅仅因为字符集是 UTF-8 并不意味着它支持 Unicode 的所有高级字符。

Unicode 支持是 PHP 6 中的主要新增功能之一,而 PHP 5 因缺乏 unicode 支持而臭名昭著。

如果您的 PHP 脚本正在生成链接,则与 apache 直接解释 url 并重定向它可能是不同的问题。

【讨论】:

【参考方案2】:

我知道 PHP 本身 可以使用 Unicode URL,因为我曾尝试在 MediaWiki(基于 PHP,也运行 WikiPedia)中使用 Unicode 页面名称并且它确实有效。例如,/index.php/Page_name© 等 URL。所以PHP可以处理它。但是 Apache 查找源文件具有 UTF-8 名称的文件可能会出现问题。

字符编码的 PHP.ini 设置不应影响这一点; Web 服务器的工作是查找特定资源,然后在确定它是 PHP 文件后调用 PHP。这意味着 Web 服务器和底层文件系统本身必须能够处理 UTF-8 文件名。

没有 mod_rewrite 规则是否可以工作?即,如果您在关闭 RewriteEngine 的情况下禁用重写引擎,然后请求 va.in/utf_dir/utf_file.php?如果是这样,则可能是 mod_rewrite 配置问题或规则问题。

当您只输入地址时,某些浏览器可能无法正确支持 URL 中的 Unicode,例如旧版浏览器。较旧的浏览器可能会跳过 UTF-8 编码步骤。不过,如果您正在关注页面上的链接,该页面是 UTF-8 编码的,这不应该阻止它工作。

【讨论】:

【参考方案3】:

我遇到了同样的问题并做了一些研究并得出以下结论。这适用于 Windows 上的 php5;在其他平台上可能是这样,但我没有检查过。

    所有 php 文件系统函数(dir、is_dir、is_file、file、filemtime、filesize、file_exists 等)仅接受和返回 ISO-8859-1 中的文件名,与程序或 ini 中设置的 default_charset 无关文件。

    如果文件名包含 unicode 字符 dir->如果有,read 会将其作为对应的 ISO-8859-1 字符返回,否则将替换为问号。

    引用文件时,例如在 is_file 或 file 中,如果您传入 UTF-8 文件名,则当该名称包含任何两个字节或更多字符时,将找不到该文件。但是,如果 UTF-8 字符可以在 ISO-8859-1 中表示,is_file(utf8_decode($filename)) 等将起作用。

换句话说,PHP5 根本无法处理名称中包含多字节字符的文件。

如果请求一个包含多字节字符的 UTF-8 URL,并且它直接对应于一个文件,PHP 将无法打开该文件,因为它无法寻址。

如果您只是想用您的语言显示漂亮的 URL,那么使用 mod_rewrite 的建议似乎是一个不错的建议。

但是,如果您要存储和检索用户上传和下载的文件,则必须解决此问题。一种方法是在服务器上使用任意(非 UTF-8)文件名,例如递增的数字,并索引数据库或 XML 文件等中的文件。另一种方法是将文件作为 BLOB 存储在数据库本身中。另一种方法(这可能更容易看到发生了什么,并且如果您的索引损坏也不会出现问题)是自己编码文件名 - 一个好的技术是在存储在服务器上时对所有传入的文件名进行 urlencode(原文如此)在为下载设置 mime 标头中的文件名之前,对它们进行磁盘和 urldecode。然后,所有甚至模糊不寻常的字符(% 除外)都被编码为 %nn,因此在很大程度上避免了文件名中的空格、跨平台支持和模式匹配的任何问题。

【讨论】:

你可以让 php 通过扫描目录并使用它找到的名称来打开文件,即使它采用不同的编码。 ***.com/questions/1525830/… -> 我会在这里查看【参考方案4】:

没有。 PHP 文件名必须是 ASCII,不管你如何设置你的服务器 PHP5 无法应付,所以我们等待 PHP 6。在 PHP 脚本中,你可以使用 utf8_decode 处理 utf-8 文件名/url。您可以使用 .htaccess 和 SQL 来解决很多问题,但无法运行 unicode 文件名。

大卫·厄尔的回答是正确的。

【讨论】:

【参考方案5】:

使用“wfio://”进行复制写入等

https://github.com/kenjiuno/php-wfio

对于文件夹:

.htaccess:

php_value auto_prepend_file C:/fix.php

修复.php:

$file = $_SERVER['SCRIPT_FILENAME'];
if (!is_readable($file)) 
    $file="wfio://".$file;
                include $file;
                exit;
        

但更适合php使用Linux操作系统

【讨论】:

以上是关于PHP 文件名(或其完整路径中的目录)可以包含 UTF-8 字符吗?的主要内容,如果未能解决你的问题,请参考以下文章

PHP 的“魔术常量”

几个 PHP 的“魔术常量”

PHP魔术方法和魔法变量详解

PATH 是不是应该包含二进制文件的目录或完整路径?

?dirname(__FILE__)

php创建多级目录完整封装类操作