Search code examples
pythonimagepython-requestsmimeebay-api

eBay API - UploadSiteHostedPictures - Python


I'm having issues trying to upload images to Ebay in Python. I have never had a problem via VBA in Excel listing items for over 6 years following the official Ebay PHP example but cannot get it to work in Python.

I keep getting "Picture Services only supports upload of JPEG, GIF, PNG, BMP, and TIFF image formats. Try again using a version of your picture saved in one of those formats." despite the image being a jpg and uploading fine via my VBA method.

I've read around and tweaked the request for 3 days to no avail. I bet it's something simple so I hope someone can point out my mistake or provide a full working example.

Changing the version doesn't make a difference and 571 still works fine for the VBA implementation.

I have no problem making a small Paypal donation to the person who can assist me in getting this working.

Thanks in advance.

with open(r"H:\temp\earth.jpg", "rb") as image_file:
    encoded_string = (base64.encodebytes(image_file.read())).decode("utf-8")

mimeBoundary = 'MIME_boundary'

ebayAuthToken = '<token>'

requestHeaders = {
    'X-EBAY-API-COMPATIBILITY-LEVEL': '1113',
    'X-EBAY-API-SITEID': '15',
    'X-EBAY-API-DEV-NAME': '<devName>',
    'X-EBAY-API-APP-NAME': '<appName>',
    'X-EBAY-API-CERT-NAME': '<certName>',
    'X-EBAY-API-CALL-NAME': 'UploadSiteHostedPictures',
    'Content-Type': 'multipart/form-data; boundary=' + mimeBoundary
}

xmlRequest = (
    '<?xml version="1.0" encoding="utf-8"?>'
    '<UploadSiteHostedPicturesRequest xmlns="urn:ebay:apis:eBLBaseComponents">'
    '<RequesterCredentials>'
    f'<eBayAuthToken>{ebayAuthToken}</eBayAuthToken>'
    '</RequesterCredentials>'
    '<PictureSet>Supersize</PictureSet>'
    '<Version>517</Version>>'
    '</UploadSiteHostedPicturesRequest>'
)

firstPart = ''
firstPart += '--' + mimeBoundary + '\r\n'
firstPart += 'Content-Disposition: form-data; name=""XML Payload"' + '\r\n'
firstPart += 'Content-Type: text/xml;charset=utf-8' + '\r\n\r\n'
firstPart += f'{xmlRequest}'
firstPart += '\r\n\r\n'

secondPart += '--' + mimeBoundary + '\r\n'
secondPart += 'Content-Disposition: form-data; name=""dummy""; filename=""dummy"' + '\r\n'
secondPart += 'Content-Transfer-Encoding: binary' + '\r\n'
secondPart += 'Content-Type: application/octet-stream' + '\r\n\r\n'
secondPart += f'{encoded_string}' # image binary data
secondPart += '\r\n'
secondPart += '--' + mimeBoundary + '--' + '\r\n'

fullRequest = firstPart + secondPart

uploadImageResponse = requests.post('https://api.ebay.com/ws/api.dll', data=fullRequest, headers=requestHeaders, verify=False)

Solution

  • I found the solution to this for anyone who has this issue in future. The request parts needed to be joined by encoding each into bytes. See below:

            tmpfile = 'H:/temp/%s.bin' % random.randint(0, 100000)
            f = open(tmpfile, 'wb')
            f.write(firstPart.encode())
            f.write(secondPart.encode())
            f.write(base64.b64decode(encoded_string))
            f.write(CRLF.encode())
            f.write(("--" + mimeBoundary + "--" + CRLF).encode())
            f.close()
            # read back what we wrote to the file
            f = open(tmpfile, 'rb')
            fullRequest = f.read()
            f.close()
    
    

    Note you don't need to write and read them to a file, this is just how the solution I found did it.