1

I would like to make a POST call in python to post a image(image is a base64 string). I'm new to making a POST call with boundary. POST call is expected to be made in below mentioned format.Any ideas on how it could be done is appreciated

POST .../api/URL_PATH
Content-Type: multipart/form-data; boundary=someboundary
Accept: application/json

--someboundary
Content-Disposition: form-data; name="entity"
Content-Type: application/json; charset=UTF-8
{
                "item": {
                                "id": 1002345,
                                "type": "type"
                },
                "name": "screenshot.png",
                "description": "This is screenshot"
}
--someboundary
Content-Disposition: form-data; name="content"; filename="screenshot.png"
Content-Type: image/png
Content-Transfer-Encoding: base64

iVBORw0KGgoAAAANSUhEUgAAALAAAAAzCAIAAAC48RV/AAAAAXNSR0IArs4c6QAAAARnQU1BAACx
jwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAALRSURBVHhe7ZjhUewwDITph3roh3qoh36OOLYc
rSRHd445YNjv17Msr2R5J9y8lxshChqCADQEAWgIAtAQBKAhCEBDEICGIAANQQAaggA0BAFoCALQ
EASgIQhAQxCAhiDAXzTE5/vrS+H1/bNFyDJoCAJ8gyE+3oLnCoOT/FZDrLzjj0FDrOM/G0LepNFn
0GaiefsIgzV/pCPAvuwqQ6h9fbZWLBFVuyX4iAJblS4LrVKsObh43UKUTtx8Uqiijh6YnDkmDBE2
07oJ5zIY1plOIdivm/HBjf4EQcUB6tXCQ72dpOjgjp6hjlTKbzfKOEZ3gVlDHLeVUfR2WgDbC4KJ
TqRb/60GUo/3gKjJWZewkRzp5SSjJeRFRULf0eN0jmaN7qgQlpHd3sVFFvyGsHMI53LHsDClraKL
ygyUmJF31fwREwn6w1HnRSMNT6CDoaxQ2+/bdn2RSUO0FjW9o3Aug2ENdYKxdLKRRdVcBEVkFYEZ
J5q+akCg04vv1ksL4UrSf/AL0ftH+gXCuQTBU51gLJ10ZEE1F0GRQS87T/tC3GmIsNlVfpgwROvu
aOGuufjguQ4OCclHNqx2RIyIP2HIi+YahbFOC6WFJL1zXvBBLhtC+j/aMgkVH0x0vG6J7MnpyOxy
w0WMiC+3sQdNfyea5kY77lgvJHm2claoLXSRlUz8yZB7G44LYELr3AcznWh/F8vfxiw3XOTspYDW
f17Udrwf7KEmMyzjEkaFYgE5fZm5H5X65vL/DOoCej8clwQzHby87ORvY5YbLhKI+GGrMedFCy1U
qGF3TAVU8iOFbJOCOnCBOUOQaYL3fgg5rywkxlrylaAhnsxVQ/jPUv9i0BB/kVVfCMeavxg0xLO5
aoiC+vFRWfJtqNAQBKAhCEBDEICGIAANQQAaggA0BAFoCALQEASgIQhAQxCAhiAADUEAGoIANAQB
aAgC0BBEcbt9ATZhuQV8mjteAAAAAElFTkSuQmCC
--a1b2c3d4--

Below is the code I tried

url = 'URL'
files = {'file': ('screenshot.png', 'base64 string')}

response = requests.post(url, auth=('*****', '******'), data={"item" : { "id": 1002345, "type": "type"
                },
                "name": "screenshot.png",
                "description": "This is screenshot"
}, files=files)
Researcher
  • 1,006
  • 7
  • 14
Ram
  • 65
  • 4
  • 12

1 Answers1

2

I believe this is what you want. Painful request to assemble! I included logging so you could see exactly what is coming out. They only way to get your content-type set on the json data was to add it as a file and manually set it with "None" filename.

import requests
import base64
import logging
import json

# Setup logging of raw requests
try:
    import http.client as http_client
except ImportError:
    # Python 2
    import httplib as http_client
http_client.HTTPConnection.debuglevel = 1

logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True


# Setup your file
subheaders = dict()
subheaders["Content-Transfer-Encoding"] = "base64"
encodedImage = base64.b64encode(open("screenshot.png", "rb").read())

# Setup separate json data
payload = {"item" : { "id": 1002345, "type": "type" },
           "name": "screenshot.png",
           "description": "This is screenshot"}

# Build Files
files = { 'entity': (None, json.dumps(payload), 'application/json; charset=UTF-8'),
          'content': ("screenshot.png", encodedImage, "image/png", subheaders) }

# POST!
url = "http://localhost:5000"
response = requests.post(url, files=files)
Researcher
  • 1,006
  • 7
  • 14
  • Thanks so much for the help. I get 403 Forbidden. Please find the logs below ```reply: 'HTTP/1.1 403 Forbidden\r\n' DEBUG:urllib3.connectionpool:https://*****:443 "POST /api/**** HTTP/1.1" 403 None header: Date: Mon, 22 Jul 2019 03:30:10 GMT header: Content-Type: application/json header: Transfer-Encoding: chunked``` – Ram Jul 22 '19 at 03:34
  • You're welcome. I'm not really sure how to help now as that code produces a request that matches exactly with what you have above. Are you able to contact the owner of the server and send them a copy of your request that the script dumps for you? – Researcher Jul 22 '19 at 09:59
  • Only thing I can think of is you're missing an api key. 403 is basically saying "go away!" https://www.lifewire.com/403-forbidden-error-explained-2617989. What type of auth are they using? – Researcher Jul 22 '19 at 10:01
  • I’m using Basic authentication. It threw 401 when auth was not passed. Now it throws 403 – Ram Jul 22 '19 at 11:03
  • In the error message, 403 None is seen. Could be due to filetype that we pass as None? – Ram Jul 22 '19 at 11:48
  • The "None" refers to the filename, which we don't want under content-disposition for entity. – Researcher Jul 23 '19 at 00:45
  • Just realised I had said filetype in the answer, changed now. – Researcher Jul 23 '19 at 01:14
  • Have you tried sending the sample to the endpoint to double check it works? – Researcher Jul 23 '19 at 01:16
  • yeah I tried sending sample png to the endpoint and it throws 403 Forbidden – Ram Jul 23 '19 at 20:26
  • Definitely need to get in touch with the owner now, sounds like a bug. – Researcher Jul 24 '19 at 01:05
  • how would the above code change if there was no file to read but a base64.encoded string? – reza Apr 12 '22 at 00:29