1

I want to send a file using requests but the server works with a fixed boundary set at *****. I'm only able to send a file but the requests module creates a random boundary. How do I overwrite it?

import requests

url='http://xxx.xxx.com/uploadfile.php'
fichier= {'uploadedfile':open('1103290736_2016_03_23_13_32_55.zip','rb')}
headers2={'Connection':'Keep-Alive','User-Agent':'Dalvik/1.6.0 (Linux; U; Android 4.4.2; S503+ Build/KOT49H)','Accept-Encoding':'gzip'}
session= requests.Session()
session.post(url,headers=headers2,files=fichier)
session.close()
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
M-Jeff
  • 23
  • 1
  • 1
  • 4

3 Answers3

4

Boy, that's one very broken server. If you can, fix the server instead.

You can't tell requests what boundary to pick. You can instead build your own multipart/form-data payload, using the email.mime package:

from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication

related = MIMEMultipart('form-data', '*****')  # second argument is the boundary.
file_part = MIMEApplication(
    open('1103290736_2016_03_23_13_32_55.zip', 'rb').read(),
    # optional: set a subtype: 'zip',
)
file_part.add_header('Content-disposition', 'form-data; name="uploadedfile"')
related.attach(file_part)

body = related.as_string().split('\n\n', 1)[1]
headers = dict(related.items())
headers['User-Agent'] = 'Dalvik/1.6.0 (Linux; U; Android 4.4.2; S503+ Build/KOT49H)'

r = session.post(url, data=body, headers=headers)

This sets Content-Type: multipart/form-data; boundary="*****" as the header, and the body uses ***** as the boundary (with appropriate -- pre- and postfixes).

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

A simple alternative is using requests-toolbelt; below example taken from this GitHub issue thread:

from requests_toolbelt import MultipartEncoder

fields = {
# your multipart form fields
}

m = MultipartEncoder(fields, boundary='my_super_custom_header')
r = requests.post(url, headers={'Content-Type': m.content_type}, data=m.to_string())

However, this introduces an extra dependency and can be slow to upload large files.

Steven Maude
  • 856
  • 11
  • 21
  • could you please give me example for fields , I tried with it and I am getting ValueError: Data must not be a string. , I have gone through https://stackoverflow.com/questions/27553082/valueerror-data-must-not-be-a-string – lazarus Jun 01 '18 at 09:11
  • Have you tested this? It doesn't seem to work as intended. I just tried it and I get a different boundary in the body than in the headers. Similar to the top of that linked github issue. – deweydb Jun 25 '18 at 23:34
1

you can actually directly use the requests module to do this:

files = {'file': ('filename', open('filename', 'rb'), 'text/plain')}
body, content_type = requests.models.RequestEncodingMixin._encode_files(files, {})

# this way you ensure having the same boundary defined in
# the multipart/form-data contetn-type header
# the form-data

data = body
headers = {
    "Content-Type": content_type
}
response = requests.post(
    endpoint,
    data=data,
    headers=headers
)

This worked for me. Otherwise I was getting an error like this:

"errorMessage":"Required request part 'file' is not present"