如何在 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 多部分/相关消息的内容类型设置“开始”属性

如何使用 java 从多部分数据中读取正文内容?

如何在PHP中更改默认页面布局的内容[关闭]

如何将这些相关索引组织成可以在 Rust 中有效查找的内容?

如何在 github 上发布 .php 页面而不是 .html 来演示一些 php 内容?

搜索引擎如何找到相关内容?