免责声明有问题的脚本还有更多问题,我不会解决这些问题,下面的答案旨在快速解决当前问题,同时希望能够启发一些无法自行诊断问题的读者。/免责声明
有两个主要问题。
问题1:分割标题行
看看这些标题:
Content-Disposition: inline;
filename=CV-IT.pdf
Content-Type: application/pdf;
name="CV-IT.pdf"
versus
Content-Type: application/pdf; name="CV-IT.pdf"
Content-Disposition: attachment; filename="CV-IT.pdf"
现在看看处理这些行的部分:
$info = split("\n",$parts[0]);
..
foreach($info as $line)
{
if( preg_match("/Content-Type: (.*);/",$line,$matches) )
{
$type = $matches[1];
}
if( preg_match("/Content-Disposition: attachment; filename=\"(.*)\"/",
$line,$matches) ) {
$name = time() . "_" . $matches[1];
}
..
}
这会将标题分成几行,然后尝试匹配每一行。现在看看两个标题。第二个(工作)有 2 条线,它们完美匹配。
第一个(不工作)有 4(!)行。这 4 行都不符合模式。
解决这个问题的方法有无数种,我将采取一个快速而肮脏的方法。添加这一行before $info = split("\n",$parts[0]);
$parts[0] = preg_replace("/\r?\n\s+/"," ",$parts[0]);
它会通过查找后跟空格的换行符并仅用一个空格替换它们,将分割标题再次转换为单行符。
问题2:错误的模式
假设您应用了上面的修复,您将得到以下模式:
if( preg_match("/Content-Disposition: attachment; filename=\"(.*)\"/", ...
尝试匹配这一行:
Content-Disposition: inline; filename=CV-IT.pdf
这里有两件事出了问题:
问题 2a:内联/附件配置
该模式清楚地寻找单词“attachment”,而该行则显示“inline”。这是通过替换来修复的attachment
by (attachment|inline)
,这表示一个替代方案。 (请注意,这也捕获了处置类型)
问题 2b:文件名双引号
该模式进一步寻找filename="(.*)"
,而该行的文件名不带引号。
这也不是主要问题,如果您插入?
之后"
,表明"
是可选的,一切都会起作用。为了使其完美,您还必须确保.
与结局不相符"
如果可用,则更换filename="(.*)"
with:
filename="?([^"]+)"?
where [^"]+
代表“除了"
'.
因此,如果您更改这些行:
if( preg_match("/Content-Disposition: attachment; filename=\"(.*)\"/",
$line,$matches) ) {
$name = time() . "_" . $matches[1];
}
into
if( preg_match('/Content-Disposition: (attachment|inline); filename="?([^"]*)"?/',
$line,$matches) ) {
$disposition = $matches[1];
$name = time() . "_" . $matches[2];
}
它应该有效。 (请注意,我更改了模式以使用单引号,这样您就无需转义双引号,从而使内容清晰易读)
为了使这个脚本万无一失,您应该真正阅读相应的 RFC,以了解电子邮件标头中还需要哪些内容。这个脚本有一个lot埋藏在其中的假设。