【问题标题】:Apache rewriting my encoded filename with special charactersApache用特殊字符重写我的编码文件名
【发布时间】:2021-04-20 15:20:25
【问题描述】:

我在下载包含“ñ”或“Ñ”等特殊字符的文件时遇到问题。

我将 rawurlencode() 应用于每个文件名。但是当我点击路由时,apache 正在重写我的 url。

<td>
  <a href="{{asset("storage/" . rawurlencode($fyi->file))}}" target="_blank">{{$fyi->name}}</a></td>

当我检查 a 标签中的 href 时,我得到了正确的 URL 编码路由,如下图所示。

a tag with encoded url

但是当我点击链接时,编码丢失了

missing encoded after hitting the link

这里是我的 apache 配置

<VirtualHost *:80>
    ServerName xxx.com
    ServerAlias xxx.con

    DocumentRoot /home/dev/xxx.com/public
    AllowEncodedSlashes On


    <Directory /home/dev/xxx.com/public>
        Options +Indexes +FollowSymLinks +MultiViews
        AllowOverride All
    Order allow,deny
    allow from all
    Require all granted
    </Directory>

    ErrorLog ${APACHE_LOG_DIR}/xxx.com-error.log
    CustomLog ${APACHE_LOG_DIR}/xxx.com-access.log combined
    RewriteEngine on
    RewriteCond %{SERVER_NAME} =xxx.com
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [QSA,L]
</VirtualHost>

【问题讨论】:

  • 这只是浏览器向您很好地显示它。检查浏览器开发工具或服务器日志中的网络选项卡,您会看到它实际上已编码。 i.stack.imgur.com/hCm7D.png
  • 哦,你是对的,好吧,所以这不是问题,所以我必须打开一个新问题,看看为什么它没有创建每个有“ñ”的文件??
  • 当您使用非 ASCII 字符(例如 ñ)时,通过 HTTP 服务器链接原始文件会变得很容易。所涉及的层(文件系统、Apache、PHP...)在编码上并不总是一致。

标签: php laravel apache


【解决方案1】:

这只是浏览器向您很好地显示它。检查浏览器开发工具或服务器日志中的网络选项卡,您会看到它实际上已编码。


真正的问题是别的——Unicode 规范化。这是一个复杂的话题,请参阅thisthis 答案以获得解释。

我们可以看到这是您问题的解决方案,因为虽然您的 original link 不起作用,但 this one 起作用。我用 N%CC%83 替换了 %C3%91(这是一个字符“N 和波浪号”),这是两个字符 - N 后跟一个“组合波浪号” - Ñ(1 个字符)与 (2 个字符) - 看起来一样,但编码不同!

tl;dr:在 Unicode 中有几种表示同一事物的方法。您将获得一个链接,其中 Ñ 作为单个字符 U+00D1 : LATIN CAPITAL LETTER N WITH TILDE,但您的实际文件似乎将 作为两个字符:U+004E : LATIN CAPITAL LETTER N 后跟 U+0303 : COMBINING TILDE

为确保其正常工作,最好确保在任何地方都使用“标准化”表示,即“NFC”形式(还有“NFD”,这是您当前的文件名)。请注意,Mac 倾向于使用 NFD,而其他 *nixes 通常使用 NFC,如果您从 Mac 上传文件而不在此过程中转换文件名,这可能会出现问题。

解决方法是在你的存储文件夹上运行convmv工具来转换所有文件的文件名:

convmv -r -i -f utf8 -t utf8 --nfc --notest .

或者(或另外)您可以尝试了解错误链接的来源,但是在 Linux 上使用 NFD 文件名无论如何都会导致错误,因为您永远不知道什么库或客户端或任何可能导致在某些时候意外规范化文件名的错误 - 当您添加一些新功能时,它可能会在几年后作为错误返回,因此最好首先确保文件名使用 NFC。


您可能会考虑的另一个选择是在数据库中建立文件元数据索引,而不是使用其实际文件名存储文件(顺便说一下,如果配置错误,这也可能导致安全漏洞),但有一些随机ID 作为名称,然后通过其 ID 识别它,并在下载时返回 Content-Disposition 标头中的原始名称,以便用户在最后获得正确的文件名。为了改善用户体验,您可以创建像 /storage/&lt;ID&gt;/&lt;nice-name&gt; 这样的 URL,其中 &lt;nice-name&gt; 仅用于显示目的(使 URL 已经显示它是什么文件)而不是用于识别实际文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-26
    • 1970-01-01
    • 2016-02-26
    • 2014-12-21
    • 1970-01-01
    相关资源
    最近更新 更多