1

Below code works absolutely fine for me when I used python's requests library. I want the same action to be done using urllib in Python3 library.

import requests

files = {'FileData': open(sample.png, 'rb')}
headers={
    "Authorization": "Basic ***********"
}
result = requests.post("https://my_sample_api_url",headers=headers,files=files)

I tried to do this post call in urllib like this, which gives me 400 Bad Request Error.

import urllib
from urllib.request import Request, urlopen

files = {'FileData': open("sample.png", "rb")}
headers={
    "Authorization": "Basic ************"
}

data_bytes = urllib.parse.urlencode(files).encode("utf-8")
result_req = Request("https://my_sample_api_url", data=data_bytes, headers=headers)
result = urlopen(image_result_req)

How can I convert this code to urllib?

halfer
  • 19,824
  • 17
  • 99
  • 186
Prathyush P
  • 413
  • 2
  • 4
  • 13

1 Answers1

1

To upload files as multipart/form-data you could use urllib along with poster library.

from poster.encode import multipart_encode
from poster.streaminghttp import register_openers
import urllib

# Register the streaming http handlers with urllib
register_openers()

# Start the multipart/form-data encoding of the file "sample.png"

# headers contains the necessary Content-Type and Content-Length
# datagen is a generator object that yields the encoded parameters
datagen, headers = multipart_encode({"image": open("sample.png")})

request = urllib.request.Request("https://my_sample_api_url", datagen, headers)

request.add_header("Authorization", "Basic ***********")

print(urllib.request.urlopen(request).read())
Harish Vutukuri
  • 1,092
  • 6
  • 14
  • Thanks for you quick reply @Harish Vutukuri, really appreciate this, but i wanted to use only python standard libraries and not any third party libraries like poster or requests. (Apologies for not mentioning this in my question). – Prathyush P Nov 26 '19 at 12:48
  • Adding to this @Harish Vutukuri, i tried with poster but pip3 install poster gives me syntax error. I guess it only supports in python2 not in python3 – Prathyush P Nov 26 '19 at 13:08
  • `requests` is the easiest way then which inbuilt support for Multipart Post Handling. I believe without any 3rd party imports this can't be achieved. – Harish Vutukuri Nov 26 '19 at 13:17
  • Hmmm... But the problem is i'm running my python script from AWS lambda and i dont want to import any third party in Lambda. Requests was an option for me but "from botocore.vendored import requests" is giving one warning saying that requests library from botocore is getting deprecated. I would appreciate if someone can give me a better solution for this. – Prathyush P Nov 29 '19 at 11:27
  • @PrathyushP could you please give this a go : https://stackoverflow.com/a/16574609 – Harish Vutukuri Nov 29 '19 at 16:42
  • Got fed up with this and used subprocess to run curl command. Everything works fine now. Thanks Everyone. – Prathyush P Jan 16 '20 at 10:59
  • For those who are thinking of using this route, please be aware the `poster` library only works in py2, `poster3` is supposedly the python3 version but it hasn't been fully converted (print missing parentheses) and has not had active development since 2018. The rabbit hole wasn't deep but it was frustrating. It's best to just use the `requests` library. – Viet Than Mar 24 '22 at 18:08