PHP – HTTP头中的文件名:有空白的问题

使用CakePHP和Java Web Start我在控制器中生成必要的.jnlp文件,其中我将文件名设置为标题字段。 这工作正常,只要我不想在文件名中使用特殊的字符。 不过,我希望在主要操作系统上启用每个可能的字符作为文件名。 所以我试图做的是通过replace它们通过空string删除所有无效的字符。 但是,在文件名中应该允许使用空格似乎存在问题。

这是代码:

$panel_id = 1 $panelname = 'whitespace 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 hitespac e',而Windows 7想要将文件保存为'Project_1_w'。 所以,似乎我的操作系统不接受文件名中未转义的空格? 如果不是以下内容,我会很满意这个解释:我留下了第4行和第5行,以便代码看起来像

 $panel_id = 1 $panelname = 'whitespace s'; $filename = sprintf('"Project_%d_%s.jnlp"', $panel_id, $panelname); $this->header('Content-Disposition: attachment; filename=' . $filename); 

而现在Windows愿意保存文件的所有空格,但我不明白为什么。 如果我使用wireshark查看头文件中的文件名,两者是相同的。 如果sprintf行被replace为$filename = 'whitespac e'或者甚至$filename = $panelname它会像在第一个codesnippet中一样切割文件名。 但是我可以使用dottet-string-concat语法replacesprintf,它可以工作。

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

不同的是双引号。 随着第一个代码,你会最终:

 Content-Disposition: attachment; filename=Project_1_w hitespace s.jnlp 

与第二个代码,你会最终:

 Content-Disposition: attachment; filename="Project_1_w hitespace s.jnlp" 

你可能想要的是这样的:

 $panel_id = 1; $panelname = 'whitespace 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始终被双引号括起来。

RFC 2616是HTTP / 1.1规范,它说:

如果用户请求将内容保存到文件中,Content-Disposition响应头字段已被提议作为原始服务器建议默认文件名的手段。 此用法源自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 ) 

一个例子是Content-Disposition:附件; 文件名= “fname.ext”

因此,发送这个:

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

符合第二种形式( quoted-string ),并应该做你期望的 – 注意只发送SPACE (ASCII dec 32 / hex 20)作为空白,而不是一些其他奇特的空白字符。