图像中的 unicode 字符 URL - 404

unicode characters in image URL - 404

我正在尝试打开名称中包含拉丁字符的图像 (113_Atlético Madrid)。

我用 PHP 函数 rawurlencode() 编码它的名字来保存它,所以现在它的新名字是 113_Atl%C3%A9tico%20Madrid。但是当我试图通过这个 URL 打开它时,例如 mysite.com/images/113_Atl%C3%A9tico%20Madrid.png 我得到了 404 错误。

我该如何解决这个问题?

PHP代码:

if(isset($_FILES['Team'])){
    $avatar = $_FILES['Team'];
    $model->avatar = "{$id}_".rawurlencode($model->name).".png";
    if(!is_file(getcwd()."/images/avatars/competitions/{$model->avatar}")){
        move_uploaded_file($avatar['tmp_name']['avatar'], getcwd()."/images/avatars/teams/{$model->avatar}");
    }
}

如果您不需要保留文件名(通常有充分的理由不这样做),那么最好简单地重命名整个文件。当前时间戳是一个合理的选择。

if(isset($_FILES['Team'])){
    $avatar = $_FILES['Team'];
    $date = new DateTime();
    $model->avatar = "{$id}_".$date->format('Y-m-d-H-i-sP').".png";
    if(!is_file(getcwd()."/images/avatars/competitions/{$model->avatar}")){
        move_uploaded_file($avatar['tmp_name']['avatar'], getcwd()."/images/avatars/teams/{$model->avatar}");
    }
}

毕竟,文件 在上传之前被 调用的内容不应该那么重要,如果两个用户在那里有一张名为 "me.png" 的图片,则更重要发生冲突的可能性要小得多。

如果您对文件名编码的想法很执着,那么我只能给您指出其他答案:

  • How do I use filesystem functions in PHP, using UTF-8 strings?
  • PHP - FTP filename encoding issue
  • PHP - Upload utf-8 filename

%-编码用于 URLs。文件名不是 URL。您使用的形式:

http://example.org/images/113_Atl%C3%A9tico%20Madrid.png

在 URL 中,Web 服务器会将其解码为类似于以下内容的文件名:

/var/www/example-site/data/images/113_Atlético Madrid.png

当您准备要放入 URL 的文件名时,您应该使用 rawurlencode(),但您不应该使用它来准备用于光盘存储的文件名。

这里还有一个额外的问题,即在磁盘上存储非 ASCII 文件名是跨平台不可靠的。特别是如果你 运行 在 Windows 服务器上,像 move_uploaded_file() 这样的 PHP 文件 API 很可能会使用你不想要的编码,你最终可能会得到像 113_Atlético Madrid.png.

这样的文件名

这个问题不一定很容易解决,但您可以使用任何形式的编码,甚至是 %-encoding。因此,如果您坚持使用当前的 rawurlencode() 来制作文件名:

/var/www/example-site/data/images/113_Atl%C3%A9tico%20Madrid.png

那没问题,但是您必须使用双 rawurlencode 来生成匹配的 URL:

http://example.org/images/113_Atl%25C3%25A9tico%2520Madrid.png

但无论如何,将潜在用户提供的任意字符串作为文件名的一部分包含在内是非常危险的。您可能会对目录遍历攻击持开放态度,其中名称包含类似 /../../ 的字符串以访问目标目录之外的文件系统。 (而且这些攻击通常升级为 PHP 应用程序的执行任意代码攻击,这些应用程序通常以弱权限部署。)你最好使用完全合成的名称,正如@MatthewBrown 所建议的 (+1) .

(请注意,允许用户文件上传的安全问题还没有结束,事实证明这是一个非常难以正确使用的功能。内容嗅探和允许图像的插件仍然存在问题文件被重新解释为其他类型的文件,从而导致跨站点脚本问题。为了防止出现这种情况,最好只提供来自单独主机名的用户提供的文件,这样针对该主机的 XSS 就不会发生让你对主站点进行 XSS。)