Reputation: 623
I am having problem uploading some images using python requests. The website I am trying to upload a photo is myauto.
When I click on it and select image, I can see in the browser network tab that on this endpoint is the request sent:
https://static.my.ge/
This is form data that is sent from browser.
First I tried to post the data using this script:
image_data = (
# 'Files[]: (binary)
('do', 'Files'),
('Func', 'UploadPhotos'),
('SiteID', 1),
('UserID', 4134977),
('IP', 'XX.XX.XX.XX'),
('UploadedFiles', 0)
)
# NOTE - we can have multiple `Files[]`
image_urls = tuple()
image_urls += (('Files[]', 'some_image.jpg'),)
response = requests.request(
method='POST',
url='https://static.my.ge/',
data=self.image_data + image_urls,
headers=headers
)
Headers I am using:
headers = {
'content-type': "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW",
'Accept-Encoding': "gzip, deflate, br",
'Accept': "*/*",
'Connection': "keep-alive",
'Host': "static.my.ge",
'Origin': "https://www.myauto.ge",
'Referer': "https://www.myauto.ge/ka/add",
'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="90", "GoogleChrome";v="90"',
'sec-ch-ua-mobile': "?0",
'Sec-Fetch-Dest': "empty",
'Sec-Fetch-Mode': "cors",
'Sec-Fetch-Site': "cross-site",
'User-Agent': "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36",
'cache-control': "no-cache"
}
But I get the following response all the time:
{'StatusID': 0, 'StatusCode': 0, 'Message': 'Incorrect Func'}
And this is the desired output:
"StatusID": 0,
"StatusCode": 1,
"Message": "Error occurred during the operation",
"Data": {
"FilesList": [
"https://static.my.ge/tmp/6db262b3d7a2f9bfd56618640b6deed8_thumbs.jpg"
],
"imgKey": [
"6db262b3d7a2f9bfd56618640b6deed8"
]
}
Then I tried to generate same Webkit Form Boundry and pass that raw string to data, but get the same result all the time. I also tried to send image blob or base64 format, but still got same error.
Then I tried to send request on this endpoint using postman, and It successfully returned the data I was expecting. I chose form-data format in body section and uploaded file through postman. Then I tried to see the logs of the requests and tried to copy it from postman and run using python script, but no success, still got same error. Finally, I tried to copy code snippet from postman code generator, but still no luck. I don't understand what is happening and ran out of ideas.
Edit:
Here is the postman script:
url = "https://static.my.ge"
payload = (
"------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: "
"form-data; name=\"Files[]\"; filename=\"some_image.jpg\"\r\n"
"Content-Type: image/jpeg\r\n\r\n\r\n"
"------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: "
"form-data; name=\"do\"\r\n\r\nFiles\r\n"
"------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: "
"form-data; name=\"SiteID\"\r\n\r\n1\r\n"
"------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: "
"form-data; name=\"UserID\"\r\n\r\n1902119\r\n"
"------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: "
"form-data; name=\"IP\"\r\n\r\nXX.XX.XX.XX\r\n"
"------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: "
"form-data; name=\"UploadedFiles\"\r\n\r\n0\r\n"
"------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: "
"form-data; name=\"Func\"\r\n\r\nUploadPhotos\r\n"
"------WebKitFormBoundary7MA4YWxkTrZu0gW--"
)
response = requests.request("POST", url, data=payload, headers=headers)
Also, found out that this is how image is represented in the request. Not sure how to do same in python code:
Update: Tried to modify postman generated script:
payload = (
"------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: "
"form-data; name=\"Files[]\"; filename=\"blob\"\r\n"
"Content-Type: image/jpg\r\n\r\n"
f"{image}\r\n"
"------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: "
"form-data; name=\"do\"\r\n\r\nFiles\r\n"
"------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: "
"form-data; name=\"SiteID\"\r\n\r\n1\r\n"
"------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: "
"form-data; name=\"UserID\"\r\n\r\n1902119\r\n"
"------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: "
"form-data; name=\"IP\"\r\n\r\nXX.XX.XX.XX\r\n"
"------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: "
"form-data; name=\"UploadedFiles\"\r\n\r\n0\r\n"
"------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: "
"form-data; name=\"Func\"\r\n\r\nUploadPhotos\r\n"
"------WebKitFormBoundary7MA4YWxkTrZu0gW--"
)
Tried to put base64 and binary images in place of f{"image"}
. But got new error message from server, not sure if it's helpful.
object(Exception)#4 (7) {
["message":protected]=>
string(34) "Invalid image file: /tmp/phpFMI89k"
["string":"Exception":private]=>
string(0) ""
["code":protected]=>
int(7)
["file":protected]=>
string(58) "/datastore/web/static.my.ge/htdocs/libs/SimpleImageNew.php"
["line":protected]=>
int(130)
["trace":"Exception":private]=>
array(3) {
[0]=>
array(6) {
["file"]=>
string(44) "/datastore/web/static.my.ge/htdocs/index.php"
["line"]=>
int(1300)
["function"]=>
string(8) "fromFile"
["class"]=>
string(14) "SimpleImageNew"
["type"]=>
string(2) "->"
["args"]=>
array(1) {
[0]=>
string(14) "/tmp/phpFMI89k"
}
}
[1]=>
array(6) {
["file"]=>
string(44) "/datastore/web/static.my.ge/htdocs/index.php"
["line"]=>
int(494)
["function"]=>
string(12) "UploadPhotos"
["class"]=>
string(7) "_Static"
["type"]=>
string(2) "->"
["args"]=>
array(0) {
}
}
[2]=>
array(6) {
["file"]=>
string(44) "/datastore/web/static.my.ge/htdocs/index.php"
["line"]=>
int(3066)
["function"]=>
string(7) "SetFunc"
["class"]=>
string(7) "_Static"
["type"]=>
string(2) "->"
["args"]=>
array(0) {
}
}
}
["previous":"Exception":private]=>
NULL
}
Upvotes: 1
Views: 2304
Reputation: 1838
I found this doing some research: https://serverfault.com/questions/694660/python-requests-image-upload-http-post
You could try that approach with the files parameter of requests.post
.
image_data = (
# 'Files[]: (binary)
('do', 'Files'),
('Func', 'UploadPhotos'),
('SiteID', 1),
('UserID', 4134977),
('IP', 'XX.XX.XX.XX'),
('UploadedFiles', 0)
)
response = requests.post(
url='https://static.my.ge/',
data=image_data,
files={'Files[]': open("some_image.jpeg",'rb')},
headers=headers
)
# Maybe the param name should be "Files" and it's value a list.
# Just try both.
response = requests.post(
url='https://static.my.ge/',
data=image_data,
files={'Files': [open("some_image.jpeg",'rb')]},
headers=headers
)
Upvotes: 1
Reputation: 12672
import requests
files = {'Files[]': ("1.png", open(r"your/image/path", 'rb'), "image/png", {})}
data = {
'Func': "UploadPhotos",
"SiteID": "1",
"UserID": "xx", # your user ID here
"IP": "xx", # your IP here
"UploadedFiles": 0
}
response = requests.post('https://static.my.ge/', files=files, data=data)
print(response.json())
And the result:
{'StatusID': 0, 'StatusCode': 1, 'Message': 'Error occurred during the operation', 'Data': {'FilesList': ['xxxx.jpg'], 'imgKey': ['xxxx']}}
Upvotes: 2
Reputation: 1838
Did you try to upload the file to a different api? I'd try to upload it to a minimalistic flask app. The following code is from the flask docs (https://flask.palletsprojects.com/en/1.1.x/patterns/fileuploads/).
Just adapt the UPLOAD_FOLDER to a folder on your machine, then you could try to do your post request to http://127.0.0.1:5000/. It should save the file to the defined upload folder. If that works, you know that you are at least doing the right thing with requests.
import os
from flask import Flask, flash, request, redirect, url_for
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = '/path/to/uploads/folder'
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit an empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('uploaded_file',
filename=filename))
return '''
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form method=post enctype=multipart/form-data>
<input type=file name=file>
<input type=submit value=Upload>
</form>
'''
if __name__ == "__main__":
print("hello")
app.run()
Upvotes: 1