PHP - HTTP-headers中的文件名:空白的问题


PHP - Filenames in HTTP-headers: Problem with whitespaces

使用CakePHP和Java Web Start,我在控制器中生成必要的.jnlp文件,其中除其他事项外,我将文件名设置为头字段。只要我不试图在文件名中使用特殊字符,就可以正常工作。但是,我想启用主操作系统上可能的每个字符作为文件名。所以我要做的是通过用空字符串替换它们来删除所有无效字符。但似乎有一个问题,空白应该允许在文件名。

这就是代码:

$panel_id = 1
$panelname = 'w h i t e s p a c e s';
$filename = sprintf('"Project_%d_%s.jnlp"', $panel_id, $panelname);
$invalid_chars = array('<', '>', '?', '"', ':', '|', '''', '/', '*', '&');
$filename = str_replace($invalid_filenamechars, '', $filename);
$this->header('Content-Disposition: attachment; filename=' . $filename);

当我这样做时,标题中的结果文件名是'Project_1_w',而Windows 7希望将文件保存为'Project_1_w'。所以我的操作系统似乎不接受文件名中未转义的空白?如果不是因为以下原因,我对这个解释会很满意:我留下了第4行和第5行,这样代码看起来就像

$panel_id = 1
$panelname = 'w h i t e s p a c e s';
$filename = sprintf('"Project_%d_%s.jnlp"', $panel_id, $panelname);
$this->header('Content-Disposition: attachment; filename=' . $filename);

现在Windows愿意保存所有空白的文件,我仍然不明白为什么。如果我使用wireshark查看头文件中的文件名,它们是相同的。如果sprint -line被$filename = 'w h i t e s p a c e'甚至$filename = $panelname取代,它会像第一个代码片段一样剪切文件名。但是我可以用点-字符串-concat语法代替sprintf,它可以工作。

谁能告诉我,我忽略了什么?

区别在于双引号。对于第一个代码,您将以:

结束
Content-Disposition: attachment; filename=Project_1_w h i t e s p a c e s.jnlp

与第二个代码,你将结束为:

Content-Disposition: attachment; filename="Project_1_w h i t e s p a c e s.jnlp"

你可能想要的是:

$panel_id = 1;
$panelname = 'w h i t e s p a c e s';
$filename = sprintf('"Project_%d_%s.jnlp"', $panel_id, $panelname);
$invalid_chars = array('<', '>', '?', '"', ':', '|', '''', '/', '*', '&');
$filename = str_replace($invalid_filenamechars, '', $filename);
$this->header('Content-Disposition: attachment; filename="'.$filename.'"');

这将去掉$filename中的任何双引号,但确保$filename始终被双引号包围。

RFC2616,这是HTTP/1.1规范,说:

Content-Disposition响应头字段已被提议作为表示源服务器建议一个默认文件名,如果用户请求将内容保存到文件中。这种用法是从来自RFC 1806中内容处置的定义。

    content-disposition = "Content-Disposition" ":"
                          disposition-type *( ";" disposition-parm )
    disposition-type = "attachment" | disp-extension-token
    disposition-parm = filename-parm | disp-extension-parm
    filename-parm = "filename" "=" quoted-string
    disp-extension-token = token
    disp-extension-parm = token "=" ( token | quoted-string )

例如附加:附件;文件名= " fname.ext "

因此,发送如下:

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

符合第二种形式(quoted-string),应该做你期望它-注意只发送SPACE (ASCII dec 32/十六进制20)作为空白,而不是其他一些花哨的空白字符。