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

PHP-HTTP头中的文件名:空格问题,php,windows,http,filenames,Php,Windows,Http,Filenames,使用CakePHP和JavaWebStart,我将在控制器中生成必要的.jnlp文件,其中包括将文件名设置为头字段。只要我不想在文件名中使用特殊字符,就可以了。但是,我想启用主操作系统上可能的每个字符作为文件名。因此,我尝试通过空字符串替换所有无效字符来删除它们。但是文件名中应该允许的空白似乎有问题 这就是代码: $panel_id = 1 $panelname = 'w h i t e s p a c e s'; $filename = sprintf('"Project_%d_%s.jnlp

使用CakePHP和JavaWebStart,我将在控制器中生成必要的.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);
现在Windows愿意保存文件及其所有空白,但我仍然不明白为什么。如果我使用wireshark查看标题中的文件名,两者都是相同的。如果sprintf行被替换为
$filename='w h it e s p a c e'
或甚至
$filename=$panelname
,它会像在第一个代码片段中一样剪切文件名。但是我可以用dottet字符串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"
使用第二个代码,您将得到:

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.'"');
$panel_id=1;
$panelname='w h i t e s p a c e s';
$filename=sprintf(“'Project\u%d\u%s.jnlp'”,$panel\u id,$panelname);
$invalid_chars=array(“,”?“,“:”,“;”,“\\”,“/”,“*”,“&”);
$filename=str\u replace($invalid\u filenamechars,,$filename);
$this->header('Content-Disposition:attachment;filename=“.$filename.”);
这会去掉$filename中的任何双引号,但会确保$filename始终被双引号包围。

这样说:

内容处置响应标头字段已建议作为 表示源服务器建议默认文件名,如果用户 请求将内容保存到文件中。此用法是派生的 根据RFC1806中内容配置的定义

    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 )
例如 内容处置:附件;filename=“fname.ext”

因此,发送此:

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

符合第二种形式(
带引号的字符串
),并且应该执行您期望的操作-注意只发送
空格
(ASCII dec 32/hex 20)作为空白字符,而不是其他一些奇特的空白字符。

严格来说,您应该在文件头中用双引号括起文件名:
Content-Disposition:attachment;filename=“My-file-name.ext“
。如果您这样做,它能解决问题吗?仅供参考,将文件名值部分定义为一个
带引号的字符串
@DaveRandom:谢谢,很高兴知道。你正处在一个错综复杂的小标准中,所有的标准都不一样。事实上,你是这样的,因为同样的事情被定义了一千次,所以很难知道该怎么做。我想我可能读过300遍RFC2616,这是我唯一真正读过的。其他RFC说你可以做很多事情,但HTTP不允许,所以我很少相信我在其他地方读到的任何东西。如果你想要一些有趣的(令人困惑的)阅读,并且有一天你会觉得无聊,那么试试(FTP)并享受所有直接冲突的语句…@DaveRandom:我最初在RFC2616中查找标题,但没有找到它(因为它在它自己的部分,与所有其他标题完全不同)。将进行编辑。相关RFC为RFC 6266。还要记住,如果需要支持ISO-8859-1范围以外的字符,还需要做更多的工作。好吧,现在我觉得自己很愚蠢。应该通过查看标题看到这一点。谢谢对诀窍是在整个头字符串周围使用单引号,在文件名周围使用双引号。有些浏览器在下载/保存文件(mac上的firefox)时会遇到问题,如果不是这样的话。