如何在 PHP 中提供多部分/相关内容?
Posted
技术标签:
【中文标题】如何在 PHP 中提供多部分/相关内容?【英文标题】:How to serve multipart/related content in PHP? 【发布时间】:2010-12-20 09:30:51 【问题描述】:说,我有一个 application/xhtml+xml 内容和一个 gif 图像。如何在单个 http get 请求(使用 php)中服务(而不是呈现)这两个?它应该是一个 multipart/related 内容。看了this RFC之后,我尝试了一些东西;但它没有用。 (不,我不是要发送带有附件的电子邮件)
提前致谢。
编辑:最后我成功了。我认为,如果我写下我是如何做到的,那将会很有用。我已将此添加为答案。请往下看。
【问题讨论】:
【参考方案1】:这是[为我工作](不,我没有使用 PHPMailer;可能有用,但我无法使其工作):
// Two contents : application/xhtml+xml and image/gif
// Here we go
<?php
$boundary = "ghorar#deem";
$im_len = filesize("path/to/abc.gif")
header("Content-Type:multipart/related; boundary=\"$boundary\"; type=\"application/xhtml+xml\"");
$xml_cnt = <<<EOD
<media xmlns="http://www.sth.com/sth.xsd">
<objectURI>cid:112509abc@syz.com</objectURI>
<size>$im_len</size>
<type>image/gif</type>
<name>abcxyz</name>
<description>blah blah</description>
</media>
EOD;
$xml_len = strlen($xml_cnt);
$im = imagecreatefromgif("path/to/abc.gif");
$to_send = "This is a multi-part message example in MIME format
--$boundary
Content-Type: application/xhtml+xml;
Content-ID: <e4509xml@asd.com>
Content-Length: $xml_len
$xml_cnt
--$boundary
Content-Type: image/gif;
Content-ID: <112509abc@syz.com>
Content-Length: $im_Len
Content-Transfer-Encoding: binary
";
echo $to_send;
imagegif($im);
echo "\r\n--$boundary--";
imagedestroy($im);
?>
您也可以从文件中加载 xml。但是,请注意,如果您的 xml 引用图像(就像我在这里所做的那样),您需要使用它的 Content-ID 来引用它。另外,请注意图像的 Content-ID 字段中的“”字符(在边界之后)和引用位置的“cid:”符号。它对我有用。感谢 Carlos Lima 为我花时间。
【讨论】:
【参考方案2】:我一直在努力实现同样的目标。
似乎 MSIE 是目前唯一支持 multipart/related 本机的浏览器(Opera 可能有一些支持 - 但我没有玩过它)但是在加载此类文件时,它似乎完全忽略了有关的 HTTP 标头mime 类型和其他内容(例如缓存信息、处置等)。事实上,MSIE 只会在 URL 具有 .mht 文件扩展名的情况下打开文件(即它违反了大多数关于 HTTP 的规则)。
此外,MSIE 将愉快地加载任何包含嵌入式多部分/相关文件(前提是它被编码为纯文本),而不呈现附件包含的数据。看起来处理这些文件的功能是允许查看文件的快速破解
如果您重新配置您的网络服务器以使用 php 解析 .mht 网址(或使用 mod_rewrite 重新映射网址),那么您可能会发现它可能会工作(尽管我不希望它与附加的查询字符串)。但是,如果您正在生成动态内容,则可能会出现问题(它不会在您期望的时候从缓存/刷新中过期)。
长话短说-它不起作用。
【讨论】:
我为移动浏览器工作,而不是为普通的桌面浏览器工作。效果很好。 phpclasses 上有一些代码应该分解一个 mhtml 文件 - 但它对我不起作用:(【参考方案3】:恐怕你不能达到你想要的目的。
据我所知,如果您想这样做以提供网页,浏览器将无法使用此类 MIME 响应来呈现页面。
如果您想了解此邮件的工作原理,请给自己发送一封带有附件的电子邮件,然后在您的电子邮件客户端(不是网络邮件)上转到电子邮件正文上的“查看源代码”选项。
您将使用 MIME 多部分编码在同一邮件中看到您的邮件、附件和可能的其他部分。
OTOH,如果您希望它发送电子邮件,可以使用 PHPMailer 等库为您完成所有编码。 如果这是您想要的,请在他们的网站上查看this example。
编辑:
您可以使用 PHPMailer 来构建消息,然后只使用结果,而不是实际发送电子邮件。
试试这样的:
** 这是未经测试的代码,仅供参考**
<?php
require_once('../class.phpmailer.php');
$mail = new PHPMailer(true); // the true param means it will throw exceptions on errors, which we need to catch
try
$mail->MsgHTML(file_get_contents('contents.html'));
$mail->AddAttachment('images/phpmailer.gif'); // attachment
$mail->AddAttachment('images/phpmailer_mini.gif'); // attachment
$mime_message = $mail->CreateBody();
echo $mime_message;
catch (phpmailerException $e)
echo $e->errorMessage(); //Pretty error messages from PHPMailer
catch (Exception $e)
echo $e->getMessage(); //Boring error messages from anything else!
?>
【讨论】:
但是必须有一种方法来提供多部分/相关文档,不是吗?否则如何实现 this(rfc-archive.org/getrfc.php?rfc=2387)? 您可以“提供”它,就像输出 MIME 多部分消息一样,但正如我所说,我认为没有浏览器会按照您期望的方式呈现它。 换句话说,如果你想要的是提供一个网页,不,它不会工作。如果您想要输出一个多部分文档以供其他东西(如邮件客户端或其他东西)使用/呈现,是的,您可以。 我尝试回显,但没有成功。 PHP header() 调用的“内容类型”应该是什么?它应该只“多部分/相关”吗?我应该使用不同的内容类型调用 header() 3 次吗?或者,只需一个 header() 调用并回显其余部分? 我将添加一个示例,只需一分钟以上是关于如何在 PHP 中提供多部分/相关内容?的主要内容,如果未能解决你的问题,请参考以下文章
在 javax.mail api 中为 mime 多部分/相关消息的内容类型设置“开始”属性
如何将这些相关索引组织成可以在 Rust 中有效查找的内容?