eBay LMS uploadFile - 无法指定具有有效格式的文件

eBay LMS uploadFile - Cannot specify file with valid format

我正在尝试使用 eBay Large Merchant Services API 批量上传电话。这个 API 和文档是出了名的糟糕(我发现了一个解释它的博客 post 并且 rails 反对它 here). The closest I can find to a working Python solution is based on this Question/Answer and his related Github 不再维护的版本。

我非常仔细地关注了这些示例,但据我所知,它们从一开始就没有完全发挥作用。我给原作者发了邮件,他说它从未投入生产。但是它应该非常接近工作。

我的所有尝试都导致 错误 11 请指定具有有效格式的文件 消息。

我尝试了多种方法来构建这个调用,使用 github 方法,或者通过 email.mime 包的方法,通过 Requests 库,以及 http.client 库.下面的输出是我认为最接近它应该是什么的。附件使用的是 Github 的 sample XML file, and it is read and gzipped using the same methods,与 Github 存储库中的一样。

如有任何帮助,我们将不胜感激。我觉得我已经用尽了我的可能性。

    POST https://storage.sandbox.ebay.com/FileTransferService
    X-EBAY-SOA-SERVICE-VERSION: 1.1.0
    Content-Type: multipart/related; boundary=MIME_boundary; type="application/xop+xml"; start="<0.urn:uuid:86f4bbc4-cfde-4bf5-a884-cbdf3c230bf2>"; start-info="text/xml"
    User-Agent: python-requests/2.5.1 CPython/3.3.4 Darwin/14.1.0
    Accept: */*
    Accept-Encoding: gzip, deflate
    X-EBAY-SOA-SECURITY-TOKEN: **MYSANDBOXTOKEN**
    X-EBAY-SOA-SERVICE-NAME: FileTransferService
    Connection: keep-alive
    X-EBAY-SOA-OPERATION-NAME: uploadFile
    Content-Length: 4863


    --MIME_boundary
    Content-Type: application/xop+xml; charset=UTF-8; type="text/xml; charset=UTF-8"
    Content-Transfer-Encoding: binary
    Content-ID: <0.urn:uuid:86f4bbc4-cfde-4bf5-a884-cbdf3c230bf2>

    <uploadFileRequest xmlns:sct="http://www.ebay.com/soaframework/common/types" xmlns="http://www.ebay.com/marketplace/services">
    <taskReferenceId>50009042491</taskReferenceId>
    <fileReferenceId>50009194541</fileReferenceId>
    <fileFormat>gzip</fileFormat>
    <fileAttachment>
    <Size>1399</Size>
    <Data><xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:urn:uuid:1b449099-a434-4466-b8f6-3cc2d59797da"/></Data>
    </fileAttachment>
    </uploadFileRequest>


    --MIME_boundary
    Content-Type: application/octet-stream
    Content-Transfer-Encoding: binary
    Content-ID: <urn:uuid:1b449099-a434-4466-b8f6-3cc2d59797da>

    b'\x1f\x8b\x08\x08\x1a\x98\xdaT\x02\xffuploadcompression.xml\x00\xcdW[W\xdb8\x10~\x0e\xbfB\x9b}\x858\xd0\xb4\x14\x8e\xebnn\x94l\xe3\x96M\xccv\xfb\xd4#\xec!\xd1V\x96\I\x06\xfc\xefw$\xdbI\x9cK\x0f\xec\xbe,\xe5P{f\xbe\xb9i\xe6\xb3\xed\xbf\x7fJ9y\x00\xa5\x99\x14\xef\xda\xa7\x9dn\x9b\x80\x88e\xc2\xc4\xe2]\xfb6\xba:y\xdb~\x1f\x1c\xf9\x83\x9c\x7f\x1fQC\xc7O\xf1\x92\x8a\x05\xcc\xe0G\x0e\xdah\x82p\xa1\xdf\xb5s%.\xe1\x8e\x16\x974c\xfa\x12\x06\xd3\x01\xd50\x94i&\x05\x08\xa3\xdb\xc1Q\xcb\xbf\x06\x9a\x80\xc2\xab\x96\xffg\x1908\xef\x9d\xfb^}c\x15sf`2\nN\xbb]\xdf\xab\xae\x11\xe9\xad\xa1-\xbf\x9f$\x13\x03i\x95\xc1\x0b\x12 \x04\xd1c\xa5\xa4\x9ab\t9]@\x00\xe2\xdb\xed\xdc\xf7\x9a\xc2\xca\xf2\x0bU\x02\xbb0\x85\x07\xe0\xc15[,}\xaf!\xaa\xcc\x0e\x95\xd2\xf2C\xd0\x1a\xfda\t\x11&\x8a8\xf2\t\x1e\xc9\xdc({y%UJ\x8d\xef\xad\x8d\x10\x83\x0e}[\x9b\xc3\xb7\xfc\x88\x19\x0e\xc1\xf5\xefC2\xffz\x12\xf6\xff\xc2\xff\xec\xdf\xc9\x84\x9c\x91\xeb\xf14\x1cG\xa4\xff)\xba\x9e\xf5\x87\x93hLB/\x1c\x8f&\xb7\xa1\xef\x95\xb8\xd2\xc7\x08t\xacXflV\xd1\x92i\x82\xbf\x94\xc4Rr\xb2\x04\x9e\x829&\xccX\xe1\x9d\xa2"!\x023\xbc+\x88Y\x02y\xa4\xc5/\xbe\xb7\x89/=\xde(\x96RU\x0c\xa9\x81\x85TE)m\xf9\xf5=V\xf2\xe6\xbcw\xe1{\x1b\x82\x12\xe8\xedE\xfasC\x95AU\x0c\xc1\xc5E\xe7\x02\x91\x1b\x92\xd2d(E\xc2l\n\xe5h\xe0llJ\x8e\x1a\xf1C\x9ae\xd8\xe0>\xe7\xf2\x11\x92 R9\xacs\xd9R\xd6\xdesa0\x1d;\t\xf5u\xa5\xc9\x95\xc2m\xb0\xaa\x11\xea\xea\xbb\xaa\xb3Lg\xd4\xc4\xcb\x88\xa5\x10\xd2\xa7\xe0\x156kKT\x1aN\x99;\xfdQ\xae\xa8k\xe3\x88\x16\xfa\xdb)\x16\xb1\xadh\x98GE\x06\xc1\x15{\x82\xc4u\xc2\x8e\xc5\n\xe1t\xd5i\xd0"\xc5\x01\x0f\xc1,e\xa2\x03\xbc\xbd\xa1\x1c[\xdd\x14\xaflQ9N)\xe3\xb8D\n\'/\xb0+\xf3\x9bb\xb8\:a:\xb6\xd5wb\x99:\x07\xdb\xb6\x95\x13\x16\x9b\\xc1\x08\x0c\xaat}\xfa\x95\xf4v6\r\x96\xc6d\x97\x9e\x07\x9d]\xb7\x1e\x9e\xff\x02\xb4\x87#\xedu\xcf\xce\xce\xbbo\xbd\xd7\xe7oN^\xbf9\xfd\xa6\xd3\xce\xdf\xd9\x02\xe3\xae\x1d\xd5S\xb3\'\xa0\x7f#\xb5\xa1|(\x13\x08z\x17\xbd\xb3\x1e\x9a\xad%\xa5\xc9\x1f9\x15\x86\x99"\xb0\xad^\xdd\x94\xba\x19\xa0Kq#9\x8bW\x03<\x83\xfb\$\x9f\xcbQ\xafy\xce\xf7\x1a\xe2\x86\xe9\x8e\xd1Zm\xbd\xeb/\xcc,\x99\xa8\x90\xe5\xa1\xf7\xac\xe9\xaer\x1f.8\xed\x11\x0b\xdaBl\xd9\xf6\xe3\x182\x03u~[\xd2\x15v\xcbl\xbf\x8f\x1aM\x0e\xc2k\xe0\x0e)\xb4\xeaV \xb9( \x19\xa8\x94\x19\x04\x1c\x13x\xb2P"\x05\x01\x0e\xb1QR\xb0\x18\x19\x07R}L,\xe1\xa49r\xf8\x1d\x10&p\x9dqK\x13\xf2\xe8\xea$X~\x82\xe5\x13yO\x14\xc4\x80\xd1:$\x04e\xc3\xe0H\xc1\x06\xd0\x91V\\x13\x82\xc3\x13\xca9\xc9h\xfc\x9d.p]\x8eIJENy\x152\xa3\x98\xdf\xa3T\xdf\x11khl\x9c0\x17\x94\x1bP\x90tH$m\xd6\xae\x9cc\x92q\xc0\x07\x89u\xefLc\x8c*SPD\x83z\xc0\xb5$F\x96\xe9=\x00\xd2\xea,\xec\xff\xea\xbc\xc9\\xad|\x90{\xa4\xfa\x0e\x19O\xc7\xc3h\xf6\xf9\xd3dH\x90\xad\xc3\xf91Ir\x07G\xaee\xe8/\x83\x98QN\x04\xb5\xc3Nb*\x84t\xf5\xd5n\x12\xeb\x07\x9d\x17\x18\x8fj\xac\xd3\xc6\xb1\xcd\xd6\x92\x03/0\xc3\x07\x9b>I\x18\xe6c\xb8\xe5p%\xf3\xc5\xb2\xf2\x8f\x1b\x8c\x11\x8c\xcd\xd36\xe3\x9e\xba\xa5R\xbaS\x1d\xe9.\xd1#3/\x99\xa3\xcb!\xae\xd6\re\xc9\xa0\xa8\xe6g\x90\x17\xa0\x90\xa7\x0f\xe9\x0f\xe2\x0f#\xebm\xdf\xdd\xcc\x95\x9b\r\x06X\xc9\xe6\xe51\x94qKr\xd8\xd6\x05\xf5}I\x86\xf8p\x11\tU\xc9:\x89\xda\xae\x19\xad\x92\xda\x0c\x83n\xa7\xbbc\xee\x14{!\xc8\x97n\x12-\x1b\x1d\x00o\x99\xecu\x83\xb4/\x95\xe3\xaf\x1d\xf8JU\x02\xc7O\x19\xa0?H\xeaJ\xeeq\xd6\x91\x95v\xe4\xae=W\n\xa0\xf6\x17\x18\xf7xl\x88l{\xbd\xc3\xfd\xf5\'\x02\xf7D\xd02\xfd\xbdv\x07\x8e\xa1j|\x03\xbf\xff\x14\xf6\x1d\x02\xae^\xf9\xf8\x9d\x8c\xf0\xc5t>j\x07g\xf8\xb6\xf0\xf6\xf0\xb9\x1c\xec\xe7\xd9\xcf\xfb\xe9p\x91\x9c\xca\xb8|*\x0f\xfb\xa5\xfd\x86\xc8\xb5\xe8y}\xf8\xff\xb4\xeb\xd5\xbfl\xd7\xab\x97\xb5\xab\x8f\xec\xc8b\xaa\xf75m\xc7x\x9c+\x99\xc1\xb3L\xfb\x9a\xd1\xe7\x19\xde\xfe\xa7\xf3\xaa5\xe5\xfb\x17\xb7\xef\xe8\r\xd1\x91[\xb8\x98\xe7\tlE\x99~\xb4+\xb7Os\x183\x19\xbd\x1c\x13~}9\xe6\xc3\xe0\xe5\x98\xf9\x87\x9fa\xe6\xc09\xa8\xbdz}\xa3\xe0\x1e\xec\xf4AE0\xcf4>\xda`\x9e\xe6\xfb\x9e\xfd\x16\x0c`@\x8bP\x1a\xa9t\xf9qX\xeb>\xde\xba\xaf\x02\xfc9\xb1\xbb\x8d\xb7n.\xbc\xfaS\xca\xf7\x9a\xdf\x8cVv\xe4{\x87\xbeiQ]\xff\xfb\x07\xe0\xf2E>\x1f\x0f\x00\x00'
    --MIME_boundary--

编辑:显示我尝试实际生成二进制数据的方法:

with open('testpayload.xml', mode='rt') as myfile:
        full_xml = myfile.read()  # replacing my full_xml with testpayload.xml, from Github repo

    # METHOD 1: Simple gzip.compress()

    payload = gzip.compress(bytes(full_xml, 'UTF-8'))

    # METHOD 2: Implementing  which should produce a gzip-compatible string with header

    import io
    out = io.BytesIO()
    with gzip.GzipFile(fileobj=out, mode="w") as f:
        f.write(bytes(full_xml, 'UTF-8'))
    payload = out.getvalue()

    # METHOD 3: Simply reading in a pre-compressed version of same testpayload.xml file. Compressed on commandline with 'gzip testpayload.xml'

    with open('testpayload.xml.gz', mode='rb') as myfile:
        payload = myfile.read()

    # METHOD 4: Adoping the _generate_date() function from github eBay-LMS-API repo http://goo.gl/YgFyBi

    mybuffer = io.BytesIO()
    fp = open('testpayload.xml', 'rb')  # This file is from https://github.com/wrhansen/eBay-LMS-API/
    # Create a gzip object that reads the compression to StringIO buffer
    gzipbuffer = gzip.GzipFile('uploadcompression.xml.gz', 'wb', 9, mybuffer)
    gzipbuffer.writelines(fp)
    gzipbuffer.close()
    fp.close()

    mybuffer.seek(0)
    payload = mybuffer.read()
    mybuffer.close()

    # DONE: send payload to API call

    r = ebay.fileTransfer_upload_file(file_id='50009194541', task_id='50009042491', gzip_data=payload)

EDIT2,QUASI-SOLUTION: Python 实际上并没有发送二进制数据,而是二进制的字符串表示,这是行不通的。我最终不得不先对文件进行 base64 编码。我以前曾尝试过,但已被 eBay 论坛上的建议放弃。我刚刚将最后一个 headers 更改为 Content-Transfer-Encoding: base64 并得到了成功响应。

EDIT3,真正的解决方案: Base 64 编码仅解决了示例 XML 文件的问题。我发现我自己的 XML 负载没有成功发送(和以前一样的错误),但是 Github 上的脚本可以很好地发送同一个文件。区别在于 Github 脚本是 Python2 并且能够无差别地混合字符串和二进制数据。要在 Python3 中发送二进制数据,我只需要做一些简单的更改,将 request_part 和 binary_part 中的所有字符串更改为字节,这样 gzip 有效负载中的字节就会与它连接。看起来像这样:

binary_part = b'\r\n'
binary_part += b'--MIME_boundary\r\n'
binary_part += b'Content-Type: application/octet-stream\r\n'
binary_part += b'Content-Transfer-Encoding: binary\r\n'
binary_part += b'Content-ID: <' + URN_UUID_ATTACHMENT.encode('utf-8') + b'>\r\n\r\n'
binary_part += gzip_data + b'\r\n'
binary_part += b'--MIME_boundary--'

所以,没有 base64 编码,只需要弄清楚如何 Python 发送真正的二进制数据。在 python2 中,原始 github 存储库 确实 像宣传的那样工作。

所以在扫描了我所有关于此的代码之后,看起来它的设置是正确的。因此,如果您的错误是一个好错误,那么这意味着您的二进制数据是错误的。你能展示你是如何压缩然后读回数据的吗?这就是我正在做的

$dir = '/.../ebayUpload.gz';
if(is_file($dir)) unlink($dir);
$gz = gzopen($dir,'w9');
gzwrite($gz, $xmlFile);
chmod($dir, 0777);
gzclose($gz);

// open that file as data;
$handle = fopen($dir, 'r');
$fileData = fread($handle, filesize($dir));
fclose($handle);

在您的情况下,$xmlFile 应该是在 https://github.com/wrhansen/eBay-LMS-API/blob/master/examples/AddItem.xml

中找到的字符串

我应该补充一点,这就是我使用 $fileData

的方式
 $binaryPart = '';
 $binaryPart .= "--" . $boundry . $CRLF;
 $binaryPart .= 'Content-Type: application/octet-stream' . $CRLF;
 $binaryPart .= 'Content-Transfer-Encoding: binary' . $CRLF;
 $binaryPart .= 'Content-ID: <urn:uuid:'.$uuid_attachment.'>' . $CRLF . $CRLF;
 $binaryPart .= $fileData . $CRLF;
 $binaryPart .= "--" . $boundry . "--";