0

I'm using Python requests and trying to upload an image to Facebook Ads API server.


I can put the image in the body using data

requests.post(endpoint, data={'pic.jpg': open('pic.jpg', 'rb')})

and then when I print the body of the request, it looks like pic.jpg=%FF%D8%FF%E0%00%10JFIF... with a looong string of those %_ things (I guess those are the bytes?)


I can also put the image in the body using files

requests.post(endpoint, files={'pic.jpg': open('pic.jpg', 'rb')})

and then when I print the body of the request, it looks like

--7bfdd12d05f549f3953f32165da5900c
Content-Disposition: form-data; name="pic.jpg"; filename="pic.jpg"

????JFIFHH??C


!1AQ"q2??????#BRW?$3b????7Cr????...

with a ton more ?'s and weird symbols.

Which is correct, if either, for doing file upload? For the top one I get back [] from the Facebook API and for the second one I get back null.

tscizzle
  • 11,191
  • 15
  • 54
  • 88
  • 1
    What does the API documentation tell you? When you use `files`, the `multipart/form-data` encoding is used, which is **usually** the correct method. – Martijn Pieters Jul 03 '14 at 15:51
  • The API documentation does not tell me anything :(( – tscizzle Jul 03 '14 at 16:16
  • https://developers.facebook.com/docs/reference/ads-api/adimage/ – tscizzle Jul 03 '14 at 16:16
  • The `-F` switch on the `curl` command appears to be the documentation. I indeed don't see anything else there, so I think the API authors are assuming a certain familiarity with HTTP and POST encodings. – Martijn Pieters Jul 03 '14 at 16:20
  • Ok, so that would indicate that `multipart/form-data` should be used, which would mean `files` is the way to go? That seems right but I still don't get the nice response so I guess I'll have to keep digging. – tscizzle Jul 03 '14 at 16:41
  • Exactly. Perhaps the auth token? – Martijn Pieters Jul 03 '14 at 16:42
  • The thing is, I use the same token in the same way for all my other API calls which do work (creating Campaigns, Sets, Custom Audiences, adding users to Custom Audiences, etc.). Images are the only thing not giving me what I want. Thanks for the help! And I will post more questions when I have some more specific details to tell/figure out. – tscizzle Jul 03 '14 at 16:45

1 Answers1

3

When you use files, the POST data is encoded as multipart/form-data, which is what you want when posting form data that includes large binary blobs of content.

If you use just data on the other hand, then application/x-www-form-urlencoded is used instead (unless you pass in just a string, then data is posted as-is).

For file uploads, you probably want the former, as multipart/form-data can also encode the mime-type and filename of the file data. Looking at the Facebook Ad API adimage enpoint their samples use curl -F, which is documented to use multipart/form-data for the upload.

Remember that also need to include a access_token in the POST:

requests.post(endpoint,
    files={'pic.jpg': open('pic.jpg', 'rb')},
    data={'access_token': '___'})

This uses both files and data, requests will combine both into one multipart/form-data POST body.

Also see What does enctype='multipart/form-data' mean? and application/x-www-form-urlencoded or multipart/form-data?

Community
  • 1
  • 1
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343