php - 有什么方法可以让 Android 的默认浏览器识别 "Content-Disposition: attachment"下载中的非 ASCII 文件名?

标签 php android utf-8 filenames content-disposition

首先,我很确定这不是重复的,因为我已经在 StackOverflow 和其他地方研究这个主题很长时间了。类似的问题已经被问到,但没有一个得到令人满意的回答。

过去的相关(但不完全相同)问题:

我也完全了解 mod_rewrite 技巧 completely unnecessary处理 HTTP header 中的文件名。但让我们假设这不是一个选项。


大多数现代浏览器(IE9+、Firefox、Chrome)都支持 RFC2231/5987下载名称中包含非 ASCII 字符的文件时。在这些情况下,以下 PHP 代码就像一个魅力:

header("Content-Disposition: attachment; " .
       "filename*=UTF-8''" . rawurlencode($filename));

IE <= 8 不理解 RFC2231/5987,但下面的代码大部分时间都有效。由于每个浏览器都试图在某种程度上模拟 IE,因此这也适用于许多其他浏览器,例如 Firefox。

header("Content-Disposition: attachment; " .
       'filename="' . rawurlencode($filename) . '"');

同时,Chrome < 11 和 Safari < 6 似乎更喜欢以下内容,尽管它会将非 ASCII 字符直接放在标题中。

header("Content-Disposition: attachment; filename=" . $filename);

到目前为止一切顺利。


但是当涉及到 Android 的默认浏览器应用程序时,一切都会分崩离析。 (到目前为止,我已经在 Gingerbread 、 Ice Cream Sandwich 和果冻 bean 中对此进行了测试。)

如果你给它标准的 RFC2231/5987 处理,默认浏览器会完全忽略它并尝试从 URL 的最后部分猜测文件名。

如果你给它通常的非标准 (IE <= 8) 处理,默认浏览器要么试图将文件名解释为 ISO-8859-1,导致无法理解的字符困惑,要么它默默地丢弃所有非-ASCII 字符。确切的行为因版本而异,但无论如何很明显,Android 的默认浏览器也不支持 rawurlencode() 格式。

如果将原始文件名放在 header 中,也会发生同样的事情。

这通常不是第三方浏览器的问题,例如 Firefox for Android、Dolphin Browser 和 Boat Browser。默认浏览器应用程序是唯一始终无法理解 UTF-8 文件名的应用程序。


也许这最终在最新版本的 Android 中得到修复,或者可能会在下一个版本中得到修复。但这不是我的问题。我需要它在现有设备中工作,而且那里仍然有数百万个 Gingerbread 和 ICS 设备。

我阅读了错误报告,阅读了投诉,几乎阅读了有关此问题的所有内容。到目前为止,我一直无法找到任何实际有效的编码方案。

如果有人知道如何编码非 ASCII 文件名**(例如 файла파일ファイル名.jpg) Content-Disposition **header 并让Android默认浏览器识别,请分享!我不在乎它有多古怪或不标准。我不在乎它是否需要针对每个 Android 版本进行定制。

更新

不幸的是,到目前为止我还没有收到任何真正解决上述问题的答案。所以赏金到期无人认领。请不要回答,除非您确实知道如何以 Android 浏览器在 ICS 之前识别的方式对非欧洲混合语言文件名进行编码,或者您有确凿证据证明这是不可能的。

最佳答案

URLUtil.java负责调用 parseContentDispositionguessFileName 使用此正则表达式 "attachment;\\s*filename\\s*=\\s*(\"? )([^\"]*)\\1\\s*$"

根据 Content-Disposition header 获取文件的文件名。

下面的源代码试图复制 parseContentDisposition 功能,在我测试它时工作正常。例如,它返回 файла파일ファイル名.jpg。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HelloWorld{

     public static void main(String []args){
     String contentDisposition = "Content-Disposition: attachment; " + " filename=" +"\"файла파일ファイル名.jpg\"";     
     Pattern CONTENT_DISPOSITION_PATTERN = Pattern.compile("attachment;\\s*filename\\s*=\\s*(\"?)([^\"]*)\\1\\s*$",Pattern.CASE_INSENSITIVE);
        try {
            Matcher m = CONTENT_DISPOSITION_PATTERN.matcher(contentDisposition);
            if (m.find()) {
                System.out.println("Result: " + m.group(2));
            }
        } catch (IllegalStateException ex) {
             // This function is defined as returning null when it can't parse the header
        }

     }
}

关于php - 有什么方法可以让 Android 的默认浏览器识别 "Content-Disposition: attachment"下载中的非 ASCII 文件名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22787697/

相关文章:

android - 在 Android SDK 中找不到 ant

python - Django 1.4 - django.db.models.FileField.save(filename, file, save=True) 产生非 ascii 文件名错误

php - fatal error :未捕获错误:调用未定义函数mysqli_connect()

android - 最终启动顺序出错 无法执行 MI 命令 -gdb-set target-async off

javascript - JS中的下拉列表并想使用PHP保存在数据库中。我不知道,可以帮助我吗?

c# - unity www "aborted"错误

php - Paypal IPN 覆盖字符集

c++ - 处理 std::wstring 和 std::string 之间的 UTF-8 编码字符串

php - 联系表无法识别 UTF-8 希腊语

php - BeautifulSoup 和 php/html 文件