Search code examples
pythonurlliburllib3

urllib: TypeError: expected string or bytes-like object


I am trying to make an API call where I pass a file in the header

import urllib.request

headers = {'files[]': open('File.sql','rb')}
datagen ={}

request = urllib.request.Request('https://www.rebasedata.com/api/v1/convert', datagen, headers)

response1 = urllib.request.urlopen(request) 
# Error : TypeError: expected string or bytes-like object

response2 = urllib.request.urlopen('https://www.rebasedata.com/api/v1/convert', datagen, headers)
#Error: 'dict' object cannot be interpreted as an integer

The error I am retrieving is:

TypeError: expected string or bytes-like object

Any help will be appreciated


Solution

  • The example you've based your code on is antiquated, and in any case, you've translated into something else – you can't read a file into a header; the example's poster library returns a body stream and the associated headers, which is not what you're doing.

    Here's how you'd do the equivalent POST with the popular requests library:

    import requests
    
    resp = requests.post(
        'https://www.rebasedata.com/api/v1/convert',
        files={'files[]': open('file.sql', 'rb')},
    )
    resp.raise_for_status()
    with open('/tmp/output.zip', 'wb') as output_file:
        output_file.write(resp.content)
    

    (If you're expecting a large output you can't buffer into memory, look into requests's stream=True mode.)

    Or, alternately (and maybe preferably, these days), you could use httpx:

    import httpx
    
    with httpx.Client() as c:
        resp = c.post(
            "https://www.rebasedata.com/api/v1/convert",
            files={"files[]": open("file.sql", "rb")},
        )
        resp.raise_for_status()
        with open("/tmp/output.zip", "wb") as f:
            f.write(resp.content)