无法使用 Python 个请求上传图片
Cannot upload images using Python requests
我在使用 python 请求上传一些图片时遇到问题。我尝试上传照片的网站是 myauto.
当我点击它和 select 图像时,我可以在浏览器网络选项卡中看到在这个端点上发送的请求:
https://static.my.ge/
这是从浏览器发送的表单数据。
并查看完整来源:
首先我尝试使用这个脚本post数据:
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 我正在使用:
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"
}
但我一直收到以下回复:
{'StatusID': 0, 'StatusCode': 0, 'Message': 'Incorrect Func'}
这是期望的输出:
"StatusID": 0,
"StatusCode": 1,
"Message": "Error occurred during the operation",
"Data": {
"FilesList": [
"https://static.my.ge/tmp/6db262b3d7a2f9bfd56618640b6deed8_thumbs.jpg"
],
"imgKey": [
"6db262b3d7a2f9bfd56618640b6deed8"
]
}
然后我尝试生成相同的 Webkit 表单边界并将该原始字符串传递给数据,但始终得到相同的结果。我也尝试发送图像 blob 或 base64 格式,但仍然出现相同的错误。
然后我尝试使用 postman 在此端点上发送请求,它成功返回了我期望的数据。我在 body 部分选择了 form-data 格式,并通过 postman 上传了文件。然后我试图查看请求的日志并尝试使用 python 脚本从 postman 和 运行 复制它,但没有成功,仍然有同样的错误。最后,我尝试从 postman code generator 复制代码片段,但仍然没有成功。我不明白发生了什么,运行 没主意。
编辑:
这是 postman 脚本:
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)
此外,发现这就是图像在请求中的表示方式。不确定如何在 python 代码中做同样的事情:
更新:
试图修改 post 人工生成的脚本:
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--"
)
尝试用 base64 和二进制图像代替 f{"image"}
。但是从服务器收到了新的错误消息,不确定是否有帮助。
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
}
您是否尝试将文件上传到其他 api?我会尝试将其上传到简约的烧瓶应用程序。以下代码来自烧瓶文档(https://flask.palletsprojects.com/en/1.1.x/patterns/fileuploads/)。
只需将 UPLOAD_FOLDER 调整为您计算机上的文件夹,然后您就可以尝试将 post 请求发送到 http://127.0.0.1:5000/。它应该将文件保存到定义的上传文件夹中。如果可行,您就知道您至少对请求做了正确的事情。
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()
我在做一些研究时发现了这个:https://serverfault.com/questions/694660/python-requests-image-upload-http-post
您可以使用 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
)
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())
结果:
{'StatusID': 0, 'StatusCode': 1, 'Message': 'Error occurred during the operation', 'Data': {'FilesList': ['xxxx.jpg'], 'imgKey': ['xxxx']}}
我在使用 python 请求上传一些图片时遇到问题。我尝试上传照片的网站是 myauto.
当我点击它和 select 图像时,我可以在浏览器网络选项卡中看到在这个端点上发送的请求:
https://static.my.ge/
这是从浏览器发送的表单数据。
并查看完整来源:
首先我尝试使用这个脚本post数据:
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 我正在使用:
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"
}
但我一直收到以下回复:
{'StatusID': 0, 'StatusCode': 0, 'Message': 'Incorrect Func'}
这是期望的输出:
"StatusID": 0,
"StatusCode": 1,
"Message": "Error occurred during the operation",
"Data": {
"FilesList": [
"https://static.my.ge/tmp/6db262b3d7a2f9bfd56618640b6deed8_thumbs.jpg"
],
"imgKey": [
"6db262b3d7a2f9bfd56618640b6deed8"
]
}
然后我尝试生成相同的 Webkit 表单边界并将该原始字符串传递给数据,但始终得到相同的结果。我也尝试发送图像 blob 或 base64 格式,但仍然出现相同的错误。
然后我尝试使用 postman 在此端点上发送请求,它成功返回了我期望的数据。我在 body 部分选择了 form-data 格式,并通过 postman 上传了文件。然后我试图查看请求的日志并尝试使用 python 脚本从 postman 和 运行 复制它,但没有成功,仍然有同样的错误。最后,我尝试从 postman code generator 复制代码片段,但仍然没有成功。我不明白发生了什么,运行 没主意。
编辑:
这是 postman 脚本:
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)
此外,发现这就是图像在请求中的表示方式。不确定如何在 python 代码中做同样的事情:
更新: 试图修改 post 人工生成的脚本:
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--"
)
尝试用 base64 和二进制图像代替 f{"image"}
。但是从服务器收到了新的错误消息,不确定是否有帮助。
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
}
您是否尝试将文件上传到其他 api?我会尝试将其上传到简约的烧瓶应用程序。以下代码来自烧瓶文档(https://flask.palletsprojects.com/en/1.1.x/patterns/fileuploads/)。
只需将 UPLOAD_FOLDER 调整为您计算机上的文件夹,然后您就可以尝试将 post 请求发送到 http://127.0.0.1:5000/。它应该将文件保存到定义的上传文件夹中。如果可行,您就知道您至少对请求做了正确的事情。
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()
我在做一些研究时发现了这个:https://serverfault.com/questions/694660/python-requests-image-upload-http-post
您可以使用 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
)
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())
结果:
{'StatusID': 0, 'StatusCode': 1, 'Message': 'Error occurred during the operation', 'Data': {'FilesList': ['xxxx.jpg'], 'imgKey': ['xxxx']}}