Python HTTP POST请求和带有MIME附件的标头多部分/相关和xop?

Python HTTP POST请求和带有MIME附件的标头多部分/相关和xop?,python,xml,mime-types,xop,ebay-lms,Python,Xml,Mime Types,Xop,Ebay Lms,我正在尝试使用eBay的FileTransfer API将批量数据交换呼叫上传到eBay。 为了做到这一点,我必须将一个xml请求字符串发布到eBay服务器,但是xml 请求包含一个部分,该部分必须包含正在传输的数据(在本例中,它是一个包含另一个xml文档的base64编码zipfile)。eBay以C#为例介绍了如何构建此类文档: 我一直在尝试用python重新创建这个示例,使用httplib发布一个字符串,我以与示例大致相同的方式构建了这个字符串(3个UUID是唯一的): 当我发布没有MIM

我正在尝试使用eBay的FileTransfer API将批量数据交换呼叫上传到eBay。 为了做到这一点,我必须将一个xml请求字符串发布到eBay服务器,但是xml 请求包含一个
部分,该部分必须包含正在传输的数据(在本例中,它是一个包含另一个xml文档的base64编码zipfile)。eBay以C#为例介绍了如何构建此类文档:

我一直在尝试用python重新创建这个示例,使用httplib发布一个字符串,我以与示例大致相同的方式构建了这个字符串(3个UUID是唯一的):

当我发布没有MIME附件信息的xml请求时,它会毫无问题地接受该文件。但是,当我尝试像上面的代码那样执行时,MIME多部分/相关附件和
标记指出了数据在附件中的位置,发布没有成功,我得到了“Error 302:Moved temporary”响应。这使我相信,我如何构造MIME多部分/相关xml请求、如何构造“Content-type”头声明、使用xop,或者很可能是三者的组合,都有问题

我想我的问题是:如何创建包含MIME多部分/相关部分并使用xop的xml请求

谢谢你的帮助


Wes

我发现我的请求有什么问题。它是构造请求字符串和头的组合。我采取了一种更有组织性和程序性的方法,而且效果很好

以下是构建请求字符串的部分的内容:

###########################################
# UUIDs
###########################################
reqUUID= uuid.uuid4()
attchmntUUID = uuid.uuid4()

##########################################
# MIME strings
##########################################
URN_UUID_REQUEST = "<0.urn:uuid:%s>"% reqUUID
URN_UUID_ATTACHMENT = "urn:uuid:%s" % attchmntUUID
MIME_BOUNDARY = "MIME_boundary"

request_dict = {
    'Size': size,
    'Data': payload,
    'fileFormat': 'gzip',
    'fileReferenceId': '50000945773',
    'taskReferenceId': '50000858033',
    'REQUUID': reqUUID,
    'ATTCHMNTUUID': attchmntUUID,
}


def build_request( request_dict):
    '''
    Build the request string with MIME Attachment
    '''

    request  = '<uploadFileRequest xmlns:sct="http://www.ebay.com/soaframework/common/types" xmlns="http://www.ebay.com/marketplace/services">\r\n'
    request += '<taskReferenceId>%s</taskReferenceId>\r\n' % request_dict['taskReferenceId']
    request += '<fileReferenceId>%s</fileReferenceId>\r\n' % request_dict['fileReferenceId']
    request += '<fileFormat>%s</fileFormat>\r\n' % request_dict['fileFormat']
    request += '<fileAttachment>\r\n'
    request += '<Size>%s</Size>\r\n'% request_dict['Size']
    request += '<Data><xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:%s"/></Data>\r\n'%URN_UUID_ATTACHMENT
    request += '</fileAttachment>\r\n'
    request += '</uploadFileRequest>\r\n'

    return request


def build_mime_message( request, data ):
    '''
    Build the xml string with MIME attachments and the base64 encoded data string
    '''

    request_part  = '\r\n'
    request_part += '--%s\r\n' % MIME_BOUNDARY
    request_part += 'Content-Type: application/xop+xml; charset=UTF-8; type="text/xml; charset=UTF-8"\r\n'
    request_part += 'Content-Transfer_Encoding: binary\r\n'
    request_part += 'Content-ID: %s\r\n\r\n' % URN_UUID_REQUEST
    request_part += '%s\r\n' % request


    binary_part  = '\r\n'
    binary_part += '--%s\r\n' % MIME_BOUNDARY
    binary_part += 'Content-Type: application/octet-stream\r\n'
    binary_part += 'Content-Transfer-Encoding: base64\r\n'
    binary_part += 'Content-ID: <%s>\r\n\r\n' % URN_UUID_ATTACHMENT
    binary_part += '%s\r\n' % data
    binary_part += '--%s--' % MIME_BOUNDARY

    return request_part + binary_part

request = build_request( request_dict )
request = build_mime_message( request, data )#data is base64 encoded gzip compressed xml file

因此,从所有这些信息中,我发现问题在于标题和请求中的换行符和制表符

我试图自己采用这个答案来使用uploadFile调用。我一直收到一个“请指定一个有效格式的文件”。我在内存中生成XML,然后用base64.standard_b64encode(gzip.compress(full_XML))压缩并将其放入base64
headers = {
'X-EBAY-SOA-OPERATION-NAME': 'uploadFile',
'X-EBAY-SOA-SERVICE-NAME': 'FileTransferService',
'X-EBAY-SOA-SECURITY-TOKEN': #Auth Token,
'Content-type': "multipart/related; boundary=" + boundary  + ";type=\"application/xop+xml\";start=\"<0." + "urn:uuid:" + str(requuid) + ">\";start-info=\"text/xml\""
}
connection = httplib.HTTPSConnection( 'storage.sandbox.ebay.com' )
connection.request( "POST", '/FileTransferService', request, headers )
###########################################
# UUIDs
###########################################
reqUUID= uuid.uuid4()
attchmntUUID = uuid.uuid4()

##########################################
# MIME strings
##########################################
URN_UUID_REQUEST = "<0.urn:uuid:%s>"% reqUUID
URN_UUID_ATTACHMENT = "urn:uuid:%s" % attchmntUUID
MIME_BOUNDARY = "MIME_boundary"

request_dict = {
    'Size': size,
    'Data': payload,
    'fileFormat': 'gzip',
    'fileReferenceId': '50000945773',
    'taskReferenceId': '50000858033',
    'REQUUID': reqUUID,
    'ATTCHMNTUUID': attchmntUUID,
}


def build_request( request_dict):
    '''
    Build the request string with MIME Attachment
    '''

    request  = '<uploadFileRequest xmlns:sct="http://www.ebay.com/soaframework/common/types" xmlns="http://www.ebay.com/marketplace/services">\r\n'
    request += '<taskReferenceId>%s</taskReferenceId>\r\n' % request_dict['taskReferenceId']
    request += '<fileReferenceId>%s</fileReferenceId>\r\n' % request_dict['fileReferenceId']
    request += '<fileFormat>%s</fileFormat>\r\n' % request_dict['fileFormat']
    request += '<fileAttachment>\r\n'
    request += '<Size>%s</Size>\r\n'% request_dict['Size']
    request += '<Data><xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:%s"/></Data>\r\n'%URN_UUID_ATTACHMENT
    request += '</fileAttachment>\r\n'
    request += '</uploadFileRequest>\r\n'

    return request


def build_mime_message( request, data ):
    '''
    Build the xml string with MIME attachments and the base64 encoded data string
    '''

    request_part  = '\r\n'
    request_part += '--%s\r\n' % MIME_BOUNDARY
    request_part += 'Content-Type: application/xop+xml; charset=UTF-8; type="text/xml; charset=UTF-8"\r\n'
    request_part += 'Content-Transfer_Encoding: binary\r\n'
    request_part += 'Content-ID: %s\r\n\r\n' % URN_UUID_REQUEST
    request_part += '%s\r\n' % request


    binary_part  = '\r\n'
    binary_part += '--%s\r\n' % MIME_BOUNDARY
    binary_part += 'Content-Type: application/octet-stream\r\n'
    binary_part += 'Content-Transfer-Encoding: base64\r\n'
    binary_part += 'Content-ID: <%s>\r\n\r\n' % URN_UUID_ATTACHMENT
    binary_part += '%s\r\n' % data
    binary_part += '--%s--' % MIME_BOUNDARY

    return request_part + binary_part

request = build_request( request_dict )
request = build_mime_message( request, data )#data is base64 encoded gzip compressed xml file
content_type_string  = 'multipart/related;'
content_type_string += ' boundary=%s;' % MIME_BOUNDARY
content_type_string += ' type="application/xop+xml";'
content_type_string += ' start="%s";' % URN_UUID_REQUEST
content_type_string += ' start-info="text/xml"'

headers = {
'X-EBAY-SOA-OPERATION-NAME': 'uploadFile',
'X-EBAY-SOA-SERVICE-NAME': 'FileTransferService',
'X-EBAY-SOA-SECURITY-TOKEN': #auth token,
'Content-Length': len( request ),
'Content-Type': content_type_string
}