Im trying to do a http 'POST' with multipart/form-data to a python GAE backend.
My server side method is receiving the complete body but i have absolutely no idea how to parse the body content without going over it manually and splitting the text for values.
My request looks like this:
POST /android/v4/MyPostMethod HTTP/1.1
Accept: */*
Accept-Charset: *
Content-Length: 186808
Content-Type: multipart/form-data; boundary=*****; charset="utf-8"
Content_Length: 186808
Content_Type: multipart/form-data; boundary=*****
Host: myhost.appspot.com
User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.1.2; GT-I9300 Build/XXXXX)
Via: HTTP/1.1 MSP-YV
--*****
Content-Disposition: form-data; name="value1"
Content-Type: text/plain; charset=UTF-8
f0ef73c5-54dd-40cf-9ee7-5c4cb764eb28
--*****
Content-Disposition: form-data; name="value2"
Content-Type: text/plain; charset=UTF-8
10d71e73-4d4d-4607-b271-f7efcfd0c59d
--*****
Content-Disposition: form-data; name="value3"
Content-Type: text/plain; charset=UTF-8
10d71e73-4d4d-4607-b271-f7efdfdfdfdf
--*****
Content-Disposition: form-data; name="logText"; filename="log.txt"
Content-Type: text/plain
Content-Transfer-Encoding: binary
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
...
--*****--
I've searched around and couldn't find a good explanation of how to do this trivial thing.
Appreciate if someone could help me here. Thanks.
For some reason cgi.FieldStorage() wasnt working for me, but only the deprecated method :
pdict = {'boundary':'*****'}
cgi.parse_multipart(self.request.body_file, pdict)
Dont know why but as long as its working im fine with that.
You want the .cgi python library.
Specifically something like this:
import cgi
form = cgi.FieldStorage()
value1 = form.getfirst("value1", "")
value2 = form.getfirst("value2", "")
value3 = form.getfirst("value3", "")
logtext = form.getfirst("logText", "")
If you want the uploaded files, you can do this
for upload in self.get_uploads():
If you want just a text field:
x = self.request.get('value1')
Related
Hi I'm looking for send multipart/form-data requests with python.
But it must contain json and file :
json content is only a some bytes equal to 1
and the file is a jpeg image
body:
--some_boundary
Content-Disposition: form-data; name="photo"; filename="myfile"
Content-Type: image/jpeg
Content-Length: 1175
IMAGE_BYTES
--some_boundary
Content-Disposition: form-data; name="media_number"
Content-Transfer-Encoding: binary
Content-Type: application/json; charset=UTF-8\x0d\x0aContent-Length: 1
1
--some_boundary
I'm trying to send it like :
[...]
json_file = open("temp.json", "w")
json_file.write("1")
files = [
('photo', ("myfile", 'image/jpeg')),
('media_number', ("", open("temp.json", 'rb'), 'application/json'))
]
r = self.session.post(url, headers=headers, files=files)
but my json seems not considered
Content-Transfer-Encoding: binary is not set maybe
Thanks for your help!
I am trying to send a POST request with Python to upload a file. I'm converting the following sample code to Python but I'm not familiar with how to set this up.
POST /path/to/upload/script HTTP/1.0
Connection: Keep-Alive
User-Agent: My Client App v1.0
Host:
https://bulksell.ebay.com/ws/eBayISAPI.dll?FileExchangeUpload
Content-type: multipart/form-data;
boundary=THIS_STRING_SEPARATES
Content-Length: 256
--THIS_STRING_SEPARATES
Content-Disposition: form-data; name="token"
12345678987654321
--THIS_STRING_SEPARATES
Content-Disposition: form-data; name="file";
filename="listings.csv"
Content-Type: text/csv
... contents of listings.csv ...
--THIS_STRING_SEPARATES
I think I need to set the headers as follows:
headers = {
"Connection": "Keep-Alive",
"User-Agent": "My Client App v1.0",
"Host": "https://bulksell.ebay.com/ws/eBayISAPI.dll?FileExchangeUpload"
"Content-type": "multipart/form-data;"
"Content-Length": "256",
"Host": "https://bulksell.ebay.com/ws/eBayISAPI.dll?FileExchangeUpload",
...
}
Do I need to include these --THIS_STRING_SEPERATES strings?
How do I include my token here? The example just sends it alone.
What would be the correct way to format this for a request.post?
Thank you.
I am trying to upload a file using POST requests in Python (requests library).
I get HTTP 400 error as a response. I think it is because my POST request is not in the format it should be. Any ideas how to convert POST request 1 into 2?
Code:
files = {"file": ("test-file.txt", open("c:/users/johndoe/desktop/test-file.txt", "rb"), "text/plain")}
response = webdriver.request("POST", "https://something.com/attachments", files = files)
What I currently have (1):
--d9bd23df892242a489b0f638d62502a6
Content-Disposition: form-data; name="file"; filename="test-file.txt"
Content-Type: text/plain
This is a test file.
Regards,
John Doe
--d9bd23df892242a489b0f638d62502a6--
What I should have (2):
-----------------------------26789175756830
Content-Disposition: form-data; name="fileName"
test-file.txt
-----------------------------26789175756830
Content-Disposition: form-data; name="fileSize"
45
-----------------------------26789175756830
Content-Disposition: form-data; name="description"
undefined
-----------------------------26789175756830
Content-Disposition: form-data; name="file"; filename="test-file.txt"
Content-Type: text/plain
This is a test file.
Regards,
John Doe
-----------------------------26789175756830--
What I think I need to add (3):
-----------------------------26789175756830
Content-Disposition: form-data; name="fileName"
test-file.txt
-----------------------------26789175756830
Content-Disposition: form-data; name="fileSize"
45
-----------------------------26789175756830
Content-Disposition: form-data; name="description"
undefined
-----------------------------26789175756830
You have to explicitly specify the fields fileName, fileSize, and description, since requests won't generate them for you automatically:
import os
import requests
filepath = 'foo'
files = {'file': open(filepath, 'rb')}
data = {
'fileName': filepath,
'fileSize': os.path.getsize(filepath),
'description': 'undefined'
}
response = requests.post('http://www.example.com/', data=data, files=files);
This generates a request like:
POST / HTTP/1.1
Connection: keep-alive
Accept: */*
Accept-Encoding: gzip, deflate
Host: www.example.com
User-Agent: python-requests/2.13.0
Content-Length: 439
Content-Type: multipart/form-data; boundary=75a7213b6b4f493fabe26feeafb8551c
Http.Entity.Parser.Multipart.Tempdir: /tmp/pZjDE
--75a7213b6b4f493fabe26feeafb8551c
Content-Disposition: form-data; name="description"
undefined
--75a7213b6b4f493fabe26feeafb8551c
Content-Disposition: form-data; name="fileSize"
16
--75a7213b6b4f493fabe26feeafb8551c
Content-Disposition: form-data; name="fileName"
foo
--75a7213b6b4f493fabe26feeafb8551c
Content-Disposition: form-data; name="file"; filename="foo"
contents of foo
--75a7213b6b4f493fabe26feeafb8551c--
I am trying to write an automatic subtitle finder in Python 3.x using The SubDB (http://thesubdb.com/api/). I'm now working on an upload feature. However, I cannot get it to work. I keep getting a 415 error (Unsupported Media Type). On the SubDB website, a 'request sample' is given:
POST /?action=upload HTTP/1.1
Host: api.thesubdb.com
User-Agent: SubDB/1.0 (Pyrrot/0.1; http://github.com/jrhames/pyrrot-cli)
Content-Length: 60047
Content-Type: multipart/form-data; boundary=xYzZY
- - --xYzZY
Content-Disposition: form-data; name="hash"
edc1981d6459c6111fe36205b4aff6c2
- - --xYzZY
Content-Disposition: form-data; name="file"; filename="subtitle.srt"
Content-Type: application/octet-stream
[PAYLOAD]
But I do not know how to interpret this and I couldn't find an answer online. This is my current code:
def uploadSubtitle(hash, path):
params = {'action': "upload", 'hash': hash}
response = requests.post(
url=base_url.format(urllib.parse.urlencode(params)),
data=open(path,'r').read(),
headers = {
'User-Agent': user_agent,
'Content-Length': 51200,
'Content-Type': "multipart/form-data; boundary=xYzZY",
'Host': "api.thesubdb.com"
}
)
return response.status_code
Any advice would be greatly appreciated!
I was having the same issues.
You may want to see this https://github.com/ivandrofly/SubDBSharp
Try following:
POST /?action=upload HTTP/1.1
Host: api.thesubdb.com
User-Agent: SubDB/1.0 (Pyrrot/0.1; http://github.com/jrhames/pyrrot-cli)
Content-Length: [Subtitle content length including boundary length]
Content-Type: multipart/form-data; boundary=xYzZY
--xYzZY
Content-Disposition: form-data; name="hash"
edc1981d6459c6111fe36205b4aff6c2
--xYzZY
Content-Disposition: form-data; name="file"; filename="subtitle.srt"
Content-Type: application/octet-stream
[SUBTITLE CONTENT]
--xYzZY
# Content-Length:
Content length should be from --xYzZY to last --xYzZY see above.
Note: Boundary started --xYzZY and ends after [SUBTITLE CONTENT]
Tested by apache-2.2.22 the python 3.3 cgi.FieldStorage() works perfectly for multipart/form-data if Content-Length is specified, however, the form data is empty if chunked transport is used. Please see the following two test cases.
Test_input_ok:
POST /cgi-bin/1.cgi?bla=ddd HTTP/1.1
Host: localhost
Content-Type: multipart/form-data; boundary=abcdefghdddddd
Content-Length: 162
--abcdefghdddddd
Content-Disposition: form-data; name="filename"; filename="freemind"
Content-Type: application/octet-stream
aaaaaaaaaa
--abcdefghdddddd--
FieldStorage result is OK: FieldStorage(None, None, [MiniFieldStorage('bla', 'ddd'), FieldStorage('filename', 'freemind', b'aaaaaaaaaa\r\n')])
Test_input_chunk_transport:
POST /cgi-bin/1.cgi?bla=ddd HTTP/1.1
Host: localhost
Transfer-Encoding: chunked
Content-Type: multipart/form-data; boundary=abcdefghdddddd
A6
--abcdefghdddddd
Content-Disposition: form-data; name="filename"; filename="freemind"
Content-Type: application/octet-stream
aaaaaaaaaa
--abcdefghdddddd--
0
Fieldstorage result for the mime attachment is empty (however, at least, present): FieldStorage(None, None, [MiniFieldStorage('bla', 'ddd'), FieldStorage(None, None, '')])
The apache server does not log any errors.
Any idea what I'm missing here?
The answers here might help you: http://pythonpaste.org/archives/message/20090313.212230.263b0ffc.da.html