PHP - HTTP标头中的文件名:空格问题

时间:2011-08-31 10:25:29

标签: php windows http filenames

使用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 h e t e c e e”,而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查看标题中的文件名,两者都是相同的。如果sprintf-line被$filename = 'w h i t e s p a c e'$filename = $panelname替换,则会像第一个代码片段一样剪切文件名。但是我可以用dottet-string-concat语法替换sprintf,它可以工作。

有谁能告诉我,我在俯瞰什么?

2 个答案:

答案 0 :(得分:7)

区别在于双引号。使用第一个代码,您最终会得到:

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始终用双引号括起来。

答案 1 :(得分:3)

RFC2616, which is the HTTP/1.1 spec,说:

  

Content-Disposition response-header字段已被提议为   表示如果用户,原始服务器建议默认文件名   请求将内容保存到文件中。导出此用法   来自RFC 1806中Content-Disposition的定义。

    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 / hex 20)作为空格,而不是其他部分花哨的空白字符。