作为Ebay API批量上传方法的一部分,我们收到来自Ebay(据称)的多部分响应,其中包含包含XML文件的zip文件的原始数据。我们在将其从原始二进制形式转换为zip文件时遇到问题。使用多部分消息底部的zip / xml文档的ebay响应的This is an example
这是我们用来测试响应的一些快速(和脏)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 docs here描述了返回的内容:
输出示例显示下载文件响应的原始格式 说明数据文件如何附加在多部分消息中。 根部分(或主体)包含标准的呼叫响应 输出字段,例如ack,timestamp和version。最后一部分 包含base64binary格式的压缩文件附件。该 文件附件流由内容ID(即cid)引用 身体的数据字段。当ack值为“Success”时,二进制 必须将文件附件的数据另存为zip文件。该 反过来,必须从zip文件中提取SoldReport XML文件。
它提到返回的内容是“base64binary”,但究竟是什么呢?它肯定不是我之前使用过的base64字符串。
答案 0 :(得分:2)
它提到返回的内容是“base64binary”,但究竟是什么呢?它当然不是我之前使用过的base64字符串。
它提到了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>)