I have made a post requests with multipart/form-data; boundary=a1c2469c-2a1f-48e6-8f1d-311f8650c855 And I get this
POST /api/feed/upload-resource HTTP/1.1
App-Id: 15762288
Version-Name: 3.26.0.451
User-Agent: Right-Android/3.26.0.451
Content-Type: multipart/form-data; boundary=a1c2469c-2a1f-48e6-8f1d-311f8650c855
Content-Length: 75412
Connection: Keep-Alive
Accept-Encoding: gzip
--a1c2469c-2a1f-48e6-8f1d-311f8650c855
Content-Disposition: form-data; name="h"
Content-Length: 4
1080
--a1c2469c-2a1f-48e6-8f1d-311f8650c855
Content-Disposition: form-data; name="w"
Content-Length: 4
1080
--a1c2469c-2a1f-48e6-8f1d-311f8650c855
Content-Disposition: form-data; name="image"; filename="/storage/emulated/0/Android/data/com.xiaoyu.rightone/tiny/tiny-738-2018-08-03-15-32-53.jpg"
Content-Type: text/plain
Content-Length: 74910
If I want to simulate this request using Python requests package How can I do that.
I have checked the document, and I have tried use file parameter like this
with open(path, 'rb') as f:
files = {
"h": "1495",
"w": "840",
"filename": ("image", f.read()),
}
r = requests.post(url, files=files)
However in my situation, I always get an error like upload_resource_empty.
This should work:
import requests
files = {
'image': ('file_name.jpg', open('file.jpg', 'rb'), 'text/plain'),
'w': (None, '123'),
'h': (None, '222')
}
response = requests.post('url', files=files)
The tuples in the dictionary have the following format: ('filename', fileobj, 'content_type', custom_headers)
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 sql query to my wordpress database using adminer script but the problem im missing somthing needed to be sent as body or headers in my opinion ( if i'm wrong please connect me )
Request raw
POST /REV/adminer-4.7.5-en.php?server=localhost&username=adepfran_wp975&db=adepfran_wp975&sql=select%20*%20from%20wplj_users HTTP/1.1
Host: mywebsite
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://mywebsite/REV/adminer-4.7.5-en.php?server=localhost&username=adepfran_wp975&db=adepfran_wp975&sql=
Content-Type: multipart/form-data; boundary=---------------------------1328964205768204682490124619
Content-Length: 425
Cookie: adminer_sid=00e0c898e031284904f8e51b591c1dee; adminer_key=320bc6e9870ffdf2f54982cb2292de87
Connection: close
Upgrade-Insecure-Requests: 1
-----------------------------1328964205768204682490124619
Content-Disposition: form-data; name="query"
select * from wplj_users
-----------------------------1328964205768204682490124619
Content-Disposition: form-data; name="limit"
-----------------------------1328964205768204682490124619
Content-Disposition: form-data; name="token"
401937:659783
-----------------------------1328964205768204682490124619--
Headers raw
-----------------------------1328964205768204682490124619
Content-Disposition: form-data; name="query"
select * from wplj_users
-----------------------------1328964205768204682490124619
Content-Disposition: form-data; name="limit"
-----------------------------1328964205768204682490124619
Content-Disposition: form-data; name="token"
401937:659783
-----------------------------1328964205768204682490124619--
also i intercepted the requests using Burp Suite to clarify further
Request raw
Request parameters
Request Headers
my actual code
ses = requests.Session()
data = {"server": "localhost",
"username": wpuser,
"db": wpdb,
"sql": "SELECT * from wplj_users"}
url="https://mywebsite/REV/adminer-4.7.5-en.php?server=localhost&username=adepfran_wp975&db=adepfran_wp975&sql=SELECT%20*%20from%20wplj_users"
request = ses.post(url,data=data )
the request without limit,query,token (Content-Disposition) does not return the wanted response , how can i pass them ?
It seems you have to send it as files=
For test I used https://httpbin.org which send back all what you get in requests so I can display it and compare with expected data
In files I used (None, "SELECT * from wplj_users") so this None will remove filename="query"
import requests
params = {
'server': 'localhost',
'username': 'adepfran_wp975',
'db': 'adepfran_wp975',
'sql': 'SELECT * from wplj_users',
}
data = {
"query": (None, "SELECT * from wplj_users"),
"limit": (None, ""),
"token": (None, "401937:659783"),
}
headers = {
'User-Agent': 'Mozilla/5.0',
#'Referer': 'https://mywebsite/REV/adminer-4.7.5-en.php?server=localhost&username=adepfran_wp975&db=adepfran_wp975&sql='
# requests.Session() should care of cookies so this header shouldn't be needed
#'Cookie': 'adminer_sid=00e0c898e031284904f8e51b591c1dee; adminer_key=320bc6e9870ffdf2f54982cb2292de87'
}
url = "https://httpbin.org/post"
#url = "https://mywebsite/REV/adminer-4.7.5-en.php"
s = requests.Session()
#r = s.get(url) # to get fresh cookies
r = s.post(url, params=params, headers=headers, files=data)
print('\n=== url ===\n')
print(r.request.url)
print('\n=== headers ===\n')
for key, val in r.request.headers.items():
print('{}: {}'.format(key, val))
print('\n=== body ===\n')
print(r.request.body.decode())
Results
=== url ===
https://httpbin.org/post?server=localhost&username=adepfran_wp975&db=adepfran_wp975&sql=SELECT+%2A+from+wplj_users
=== headers ===
User-Agent: Mozilla/5.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Length: 331
Content-Type: multipart/form-data; boundary=79f18e4306b943ea92a49bae21b51b9c
=== body ===
--79f18e4306b943ea92a49bae21b51b9c
Content-Disposition: form-data; name="query"
SELECT * from wplj_users
--79f18e4306b943ea92a49bae21b51b9c
Content-Disposition: form-data; name="limit"
--79f18e4306b943ea92a49bae21b51b9c
Content-Disposition: form-data; name="token"
401937:659783
--79f18e4306b943ea92a49bae21b51b9c--
I am using Python's (3.5.2) requests library (2.12.4) to post a query to the Primer-BLAST website. Below is the script I've written for this task:
#!/usr/bin/env python
import requests
# BaseURL being accessed
url = 'https://www.ncbi.nlm.nih.gov/tools/primer-blast/primertool.cgi'
# Dictionary of query parameters
data = {
'INPUT_SEQUENCE' : 'TCTTCTGAGAAAGTCTGAGGCTCCTTAGTACCTTCTCTAGTATGAACTGTTCAGCCTGCCCGCAAGTTGTAACTACGCAGGCGCCAAGACAGCCAACCAAGGAGGCTGCAGA',
'ORGANISM' : 'Mus musculus'
}
# Make a POST request and read the response
with requests.session() as session:
poster = session.post(url, data=data)
for key, value in poster.headers.items():
print(key, ':', value)
I need to retrieve the NCBI-RCGI-RetryURL field from the response's header information. However, I can only see this field when I use the HTTP trace extension in Google Chrome. Below is the full trace of the POST and response using Google Chrome:
POST https://www.ncbi.nlm.nih.gov/tools/primer-blast/primertool.cgi
Origin: https://www.ncbi.nlm.nih.gov
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryBflp51Ny9ReeA5A9
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: https://www.ncbi.nlm.nih.gov/tools/primer-blast/index.cgi?LINK_LOC=reset
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
Cookie: sv-userdata-key-www.ncbi.nlm.nih.gov=G5KxXzyQ81U_vs1aHK_7XDWciF1B8AjjDUmDunVbhIZhZ4p4t_SVK4ASpbTT8iDSJVcxBH9oUAB3K2xNWjp3G0koYCloBlYuSxdoIGIkYzl2; ncbi_sid=0751457F9A561D01_0000SID; _ga=GA1.2.567134514.1503994317; _gid=GA1.2.654339584.1503994317; _gat=1; starnext=MYGwlsDWB2CmAeAXAXAbgK7RAewIYBM4lkAmAXgAcAnMAW1ioCMRcBnRAMgBYzm3FWsXFWAALDgEZymHAUkBOMgAYA7AFYpXFQDF5AQTUA2ACIBRFRKVXrN2xI4klygMJcSltQA59R0wGY/S1tg63t3Shp6JhZ2AFI/PQA5AHlE03i9PnZBYTEMlLSHcgB3UoA6aGBGMAqQWgqwUTKAc2wANwceajoGLMR81NMHQwie6P4BtIy+nJFxEhVRqL7J9ISZoTnVh08l3pj+lWcC9KON3NFYo5OHRQkuLiUOPyd5K2eJMnvH5/JPDWefjIADNcCBBM8eIgqOhYM81F83GpniMJH4SPJnosSFxnrtAoZ5Li/IoXp5DCpuE50RIpNxPlIAtxyNBcIgwG04Q8yDI8IQEJwuAiSBw1EDvk81DxPEo/KKEfIRUYyCRDIZRYtJbtaT81HcOIYnE9DAycUA=
HTTP/1.1 200 OK
Date: Tue, 29 Aug 2017 13:38:27 GMT
Server: Apache
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Referrer-Policy: origin-when-cross-origin
Content-Security-Policy: upgrade-insecure-requests
Cache-Control: no-cache, no-store, max-age=0, private, must-revalidate
Expires: 0
NCBI-PHID: 0C421A7A9A56E5310000000000000001.m_2
NCBI-RCGI-RetryURL: https://www.ncbi.nlm.nih.gov/tools/primer-blast/primertool.cgi?ctg_time=1504013907&job_key=aWO2H68Wor6FhLSBueGQs8P6gYHu6Zqc7w
NCBI-SID: 0751457F9A561D01_0000SID
Pragma: no-cache
Access-Control-Allow-Methods: POST, GET, PUT, OPTIONS, PATCH, DELETE
Access-Control-Allow-Origin: https://www.ncbi.nlm.nih.gov
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Origin,X-Accept-Charset,X-Accept,Content-Type,X-Requested-With,NCBI-SID,NCBI-PHID
Content-Type: text/html
Set-Cookie: ncbi_sid=0751457F9A561D01_0000SID; domain=.nih.gov; path=/; expires=Wed, 29 Aug 2018 13:38:27 GMT
Vary: Accept-Encoding
Content-Encoding: gzip
X-UA-Compatible: IE=Edge
X-XSS-Protection: 1; mode=block
Keep-Alive: timeout=1, max=9
Connection: Keep-Alive
Transfer-Encoding: chunked
And here is all the header information I get from my script:
Date : Tue, 29 Aug 2017 14:41:08 GMT
Server : Apache
Strict-Transport-Security : max-age=31536000; includeSubDomains; preload
Referrer-Policy : origin-when-cross-origin
Content-Security-Policy : upgrade-insecure-requests
Accept-Ranges : bytes
Vary : Accept-Encoding
Content-Encoding : gzip
X-UA-Compatible : IE=Edge
X-XSS-Protection : 1; mode=block
Content-Length : 2516
Keep-Alive : timeout=1, max=10
Connection : Keep-Alive
Content-Type : text/html
The NCBI-RCGI-RetryURL field is important because it contains the URL I need to execute a GET request on in order to retrieve the results.
EDIT:
Updated script as per Maurice Meyer's suggestion:
#!/usr/bin/env python
import requests
# BaseURL being accessed
url = 'https://www.ncbi.nlm.nih.gov/tools/primer-blast/primertool.cgi'
# Dictionary of query parameters
data = {
'INPUT_SEQUENCE' : 'TCTTCTGAGAAAGTCTGAGGCTCCTTAGTACCTTCTCTAGTATGAACTGTTCAGCCTGCCCGCAAGTTGTAACTACGCAGGCGCCAAGACAGCCAACCAAGGAGGCTGCAGA',
'ORGANISM' : 'Mus musculus'
}
# Extra headers
headers = {
'Origin' : 'https://www.ncbi.nlm.nih.gov',
'Upgrade-Insecure-Requests' : '1',
'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.101 Safari/537.36',
'Content-Type' : 'multipart/form-data; boundary=----WebKitFormBoundaryBflp51Ny9ReeA5A9',
'Accept' : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Referer' : 'https://www.ncbi.nlm.nih.gov/tools/primer-blast/index.cgi?LINK_LOC=reset',
'Accept-Encoding' : 'gzip, deflate, br',
'Accept-Language' : 'en-US,en;q=0.8',
'Cookie' : 'sv-userdata-key-www.ncbi.nlm.nih.gov=G5KxXzyQ81U_vs1aHK_7XDWciF1B8AjjDUmDunVbhIZhZ4p4t_SVK4ASpbTT8iDSJVcxBH9oUAB3K2xNWjp3G0koYCloBlYuSxdoIGIkYzl2; ncbi_sid=0751457F9A561D01_0000SID; _ga=GA1.2.567134514.1503994317; _gid=GA1.2.654339584.1503994317; _gat=1; starnext=MYGwlsDWB2CmAeAXAXAbgK7RAewIYBM4lkAmAXgAcAnMAW1ioCMRcBnRAMgBYzm3FWsXFWAALDgEZymHAUkBOMgAYA7AFYpXFQDF5AQTUA2ACIBRFRKVXrN2xI4klygMJcSltQA59R0wGY/S1tg63t3Shp6JhZ2AFI/PQA5AHlE03i9PnZBYTEMlLSHcgB3UoA6aGBGMAqQWgqwUTKAc2wANwceajoGLMR81NMHQwie6P4BtIy+nJFxEhVRqL7J9ISZoTnVh08l3pj+lWcC9KON3NFYo5OHRQkuLiUOPyd5K2eJMnvH5/JPDWefjIADNcCBBM8eIgqOhYM81F83GpniMJH4SPJnosSFxnrtAoZ5Li/IoXp5DCpuE50RIpNxPlIAtxyNBcIgwG04Q8yDI8IQEJwuAiSBw1EDvk81DxPEo/KKEfIRUYyCRDIZRYtJbtaT81HcOIYnE9DAycUA='
}
# Make a POST request and read the response
with requests.session() as session:
poster = session.post(url, data=data, headers=headers)
for key, value in poster.headers.items():
print(key, ':', value)
Updated output, still no difference:
Date : Tue, 29 Aug 2017 15:05:27 GMT
Server : Apache
Strict-Transport-Security : max-age=31536000; includeSubDomains; preload
Referrer-Policy : origin-when-cross-origin
Content-Security-Policy : upgrade-insecure-requests
Accept-Ranges : bytes
Vary : Accept-Encoding
Content-Encoding : gzip
X-UA-Compatible : IE=Edge
X-XSS-Protection : 1; mode=block
Content-Length : 2517
Keep-Alive : timeout=1, max=10
Connection : Keep-Alive
Content-Type : text/html
The request data between the two is totally different.
Specifically the request body data. So it really isn't missing header information using Python's requests library - it is missing information the in POST request to server.
You can't simply copy and paste the header
'Content-Type' : 'multipart/form-data; boundary=----WebKitFormBoundaryBflp51Ny9ReeA5A9',
Or just post the data INPUT_SEQUENCE and ORGANISM like that - also in any case the data you do have for ORGANISM is clearly wrong - a cursory glance shows it would be Mus musculus (taxid:10090) not Mus musculus.
So - you need to look at the whole request - headers and body, then craft a request that includes the required data by the server. Looking at it you are missing loads and loads of data that the server will need to respond.
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="INPUT_SEQUENCE"
TCTTCTGAGAAAGTCTGAGGCTCCTTAGTACCTTCTCTAGTATGAACTGTTCAGCCTGCCCGCAAGTTGTAACTACGCAGGCGCCAAGACAGCCAACCAAGGAGGCTGCAGA
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="SEQFILE"; filename=""
Content-Type: application/octet-stream
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER5_START"
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER5_END"
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER3_START"
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER3_END"
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_LEFT_INPUT"
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_RIGHT_INPUT"
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_PRODUCT_MIN"
70
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_PRODUCT_MAX"
1000
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_NUM_RETURN"
10
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_MIN_TM"
57.0
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_OPT_TM"
60.0
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_MAX_TM"
63.0
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_MAX_DIFF_TM"
3
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_ON_SPLICE_SITE"
0
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="SPLICE_SITE_OVERLAP_5END"
7
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="SPLICE_SITE_OVERLAP_3END"
4
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="MIN_INTRON_SIZE"
1000
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="MAX_INTRON_SIZE"
1000000
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="SEARCH_SPECIFIC_PRIMER"
on
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="SEARCHMODE"
0
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="PRIMER_SPECIFICITY_DATABASE"
refseq_mrna
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="CUSTOM_DB"
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="CUSTOMSEQFILE"; filename=""
Content-Type: application/octet-stream
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
Content-Disposition: form-data; name="ORGANISM"
Mus musculus (taxid:10090)
------WebKitFormBoundaryJVAJqDi2cI4BTfmc
etc...
I'm having some difficulties parsing multipart form data when using the django-rest-framework. I've set up a minimal view to just echo back the request data:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.parsers import MultiPartParser, FormParser
class FileUpload(APIView):
parser_classes = (MultiPartParser, FormParser, )
def post(self, request, format=None, *args, **kwargs):
return Response({'raw': request.data, 'data': request._request.POST,
'files': str(request._request.FILES)})
I am expecting that raw (slightly badly named I admit) contains effectively the same data as request._request.POST and request._request.FILES.
If I POST to the view with Content-Type= application/x-www-form-urlencoded this works as expected:
$ http -v --form POST http://localhost:8000/upload/api/ course=3 name=name
POST /upload/api/ HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 18
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: localhost:8000
User-Agent: HTTPie/0.9.2
course=3&name=name
HTTP/1.0 200 OK
Allow: POST, OPTIONS
Content-Type: application/json
Date: Thu, 17 Dec 2015 16:52:37 GMT
Server: WSGIServer/0.2 CPython/3.4.3
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN
{
"data": {
"course": "3",
"name": "name"
},
"files": "<MultiValueDict: {}>",
"raw": {
"course": "3",
"name": "name"
}
}
However if I post with Content-Type=multipart/form-data I get the following:
$ http -v --form POST http://localhost:8000/upload/api/ file#~/Projects/lms/manage.py course=3 name=name
POST /upload/api/ HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 577
Content-Type: multipart/form-data; boundary=634ec7c7e89a487b89c1c07c0d24744c
Host: localhost:8000
User-Agent: HTTPie/0.9.2
--634ec7c7e89a487b89c1c07c0d24744c
Content-Disposition: form-data; name="course"
3
--634ec7c7e89a487b89c1c07c0d24744c
Content-Disposition: form-data; name="name"
name
--634ec7c7e89a487b89c1c07c0d24744c
Content-Disposition: form-data; name="file"; filename="manage.py"
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
--634ec7c7e89a487b89c1c07c0d24744c--
HTTP/1.0 200 OK
Allow: POST, OPTIONS
Content-Type: application/json
Date: Thu, 17 Dec 2015 16:55:44 GMT
Server: WSGIServer/0.2 CPython/3.4.3
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN
{
"data": {
"course": "3",
"name": "name"
},
"files": "<MultiValueDict: {'file': [<InMemoryUploadedFile: manage.py ()>]}>",
"raw": {}
}
Am I missing something here? I am using HTTPIE to generate the requests here but the same behaviour exists with curl so I'm pretty sure that is not the problem. I am using djangorestframework==3.3.0 and Django==1.8.4
EDIT:
It seems that PUTing to the url (with an otherwise identical request) achieves the desired result:
$ http -v --form PUT http://localhost:8000/upload/api/ file#~/Projects/lms/manage.py course=3 name=name
PUT /upload/api/ HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 577
Content-Type: multipart/form-data; boundary=98feb59a8abe4bfb95a7321f536ed800
Host: localhost:8000
User-Agent: HTTPie/0.9.2
--98feb59a8abe4bfb95a7321f536ed800
Content-Disposition: form-data; name="course"
3
--98feb59a8abe4bfb95a7321f536ed800
Content-Disposition: form-data; name="name"
name
--98feb59a8abe4bfb95a7321f536ed800
Content-Disposition: form-data; name="file"; filename="manage.py"
#!/usr/bin/env python
import os
import sys
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.local")
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
--98feb59a8abe4bfb95a7321f536ed800--
HTTP/1.0 200 OK
Allow: POST, PUT, OPTIONS
Content-Type: application/json
Date: Thu, 17 Dec 2015 18:10:34 GMT
Server: WSGIServer/0.2 CPython/3.4.3
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN
{
"data": {},
"files": "<MultiValueDict: {}>",
"raw": "<QueryDict: {'name': ['name'], 'course': ['3'], 'file': [<InMemoryUploadedFile: manage.py ()>]}>"
}
So I could just use PUT. That is however not ideal as the client does not control what the file is named or where it is located on the server. POST is more appropriate in that sense. In any sense, I don't see why PUT works when POST doesn't.
It is a known issue for the version you're using. Upgrading django rest framework to the latest version will solve the problem. However, you can PUT the request as a workaround.
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]