php - 从内联二进制附件创建 zip 到多部分消息

标签 php xml zip ebay-api ebay-lms

作为 eBay API 批量上传方法的一部分,我们从 eBay 收到了多部分响应(据称),其中包含包含 XML 文件的 zip 文件的原始数据。我们在将其从原始二进制形式转换为 zip 文件时遇到问题。 This is an example eBay 响应的 zip/xml 文档位于多部分消息的底部。

这是我们用来测试响应的一些快速(但肮脏)的 PHP:

$fpath = "http://developer.ebay.com/DevZone/file-transfer/CallRef/Samples/downloadFile_basic_out_xml.txt";
$responseXml = file_get_contents($fpath);
$endofxmlstring = "</downloadFileResponse>";
$pos = strpos($responseXml, $endofxmlstring) + 1; //plus one to catch the final return
$zipbuffer = substr($responseXml, $pos + strlen($endofxmlstring));
unset($responseXml);

$startofzipstring = "Content-ID:";
$pos = strpos($zipbuffer, $startofzipstring);
$zipbuffer = substr($zipbuffer, $pos);

$startofzipstring = "PK";
$pos = strpos($zipbuffer, $startofzipstring);
$zipbuffer = substr($zipbuffer, $pos);

$handler = fopen("response.zip", 'wb') or die("Failed. Cannot Open file to Write!");
fwrite($handler,$zipbuffer);
fclose($handler);

zip 文件已创建,但已损坏。传递到 $zipbuffer 中的 zip 文件的内容似乎是正确的代码(与响应内容底部的代码相同),所以我不确定发生了什么上。

eBay 文档 here描述此处返回的内容:

The output sample shows the raw format of the download file response to illustrate how the data file is attached in the multi-part message. The root part (or body) contains the call response with the standard output fields, such as ack, timestamp, and version. The final part contains the compressed file attachment in base64binary format. The file attachment stream is referenced by content ID (i.e., cid) in the Data field of the body. When the ack value is "Success," the binary data of the file attachment must be saved as a zip file. The SoldReport XML file must, in turn, be extracted from the zip file.

它提到返回的内容是“base64binary”,但这实际上是什么?这肯定不是我以前使用过的 Base64 字符串。

最佳答案

It mentions the returned content is "base64binary" but what actually is this? It's certainly not a base64 string that i've worked with before.

它在 XML 中提到了这一点。但请记住,XML 位于 ZIP 内部,而 ZIP 是多部分响应(HTTP 消息)的最后一部分。

好吧,这听起来有点像自作聪明,这里有一个好方法来提醒这一点:base64binary 最常在 XML 上下文中使用,因为 XML 不能包含完整的二进制数据(例如,NUL 字节不起作用)我们知道二进制数据可以包含它们,因为不支持其他一些字符)。因此,如果您发现 base64binary 和 XML 即将出现,那么假设两者属于一起并没有错。

对于给定的 HTTP 示例,您是完全正确的:其中没有 base64:

...
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
                           ######
Content-ID: <urn:uuid:D8D75F18A8343F8FC61226972901992>

PKÙÔG²x7œÿwšÌÐÛ?žû›ÚE0uRßÔçÒ©]SŒçÔU mSkèSkèS«·SÏ[M=o•Z¿N­_§þ:Kýu–úë,õÌ]
ê[ÈS'%¦¾Ù'uTcjGêÁÏÔ$IjKjKjKê¸ÎÔóV©ôÔzê?¯Ôdij²4uF\6݈ôÌ]jIjÂ<µ‹#õÕB©¯J=
ö˜:¨0».C-åiÙèl¢Ijå(õÜ_jÆ>5cŸ:(/µ—&õØ]jÉ µd?ú^›Ô9?©‡þRý¥NJLí©Kí©Kí©K-¦–K‡cÃÒáØ0W¹

这里的传输编码显然是二进制的。

您应该在此处使用 HTTP 客户端,它能够对分块响应进行分块,并且还可以很好地处理多部分响应。

$startofzipstring = "PK";
$pos = strpos($zipbuffer, $startofzipstring);
$zipbuffer = substr($zipbuffer, $pos);

如果最后一部分被分块,则可能会失败。


您通过 Ebay 提供的示例数据有些损坏,因此测试起来并不容易,但如果您安装 HTTP extension of PHP处理多部分文档有些简单。这可能不是 100% RFC 符合,但我认为对于少量的代码来说这是相当不错的,而且比我通过快速搜索在 Stackoverflow 上找到的其他示例更严格:

$url = 'http://developer.ebay.com/DevZone/file-transfer/CallRef/Samples/downloadFile_basic_out_xml.txt';
$raw = file_get_contents('downloadFile_basic_out_xml.txt');

$message = MultipartHttpMessage::fromString($raw);

echo 'Boundary: ', $message->getBoundary(), "\n";

foreach ($message->getParts() as $index => $part) {
    printf("Part #%d:\n", $index);
    foreach ($part->getHeaders() as $name => $value) {
        printf("  %s: %s (%s)\n", $name, $value[NULL], $value);
    }
}

输出:

Boundary: MIMEBoundaryurn_uuid_9ADF5C1A6F530C078712269728985463257
Part #0:
  Content-Type: application/xop+xml (application/xop+xml; charset=utf-8; type="text/xml")
  Content-Transfer-Encoding: binary (binary)
  Content-Id: <0.urn:uuid:9ADF5C1A6F530C078712269728985463258> (<0.urn:uuid:9ADF5C1A6F530C078712269728985463258>)
Part #1:
  Content-Type: application/octet-stream (application/octet-stream)
  Content-Transfer-Encoding: binary (binary)
  Content-Id: <urn:uuid:D8D75F18A8343F8FC61226972901992> (<urn:uuid:D8D75F18A8343F8FC61226972901992>)

代码:https://gist.github.com/hakre/f13e1d633301bf5f221c

关于php - 从内联二进制附件创建 zip 到多部分消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19689166/

相关文章:

php - 每当使用 £ 时,MySQL 或 PHP 都会附加一个 Â

php - 阻止浏览器询问用户是否要刷新页面

xml - <xs :group> and <xs:attributeGroup>? 和有什么区别

xml - 关于 XPath

java - 我正在尝试使用 zip4j jar 文件提取受密码保护的 ZIP 文件,但出现以下错误

java - 如何在 Java 中创建未压缩的 Zip 存档

php - mysql查询只返回一个字的字符串

php - 从 mySQL 表中识别作业代码的更改

java - 从 OMElement 对象获取 InputStream/io.Reader

安卓解压打开失败: ENOENT (No such file or directory)