从Python客户端向Flask服务器上传图片

3 投票
2 回答
7768 浏览
提问于 2025-04-17 21:46

我正在使用 requestsrequests_toolbelt 来把一张图片发送到云端,目前我写的代码大概是这样的:

import requests
import json
from requests_toolbelt import MultipartEncoder

m = MultipartEncoder(
    fields={"user_name":"tom", "password":"tom", "method":"login",
            "location":"landing", "cam_id":"c00001", "datetime":"hammaTime!"
            ,'image': ('filename', open('image.jpg', 'rb'))}
    )
r = requests.post(url, data=m)
print r.text

当图片到达服务器后,我该如何获取一个可以使用的字典呢?toolbelt 的文档 只展示了如何发送数据,并没有说明如何在接收端处理这些数据。有什么建议吗?

2 个回答

1

requests-toolbelt 这个工具只能把文件发送到服务器,至于怎么在服务器上保存这些文件,以及返回有用的结果,就得靠你自己了。你可以创建一个 Flask 的接口来处理文件上传,然后返回一个包含你想要结果的字典,以 JSON 格式返回,最后在客户端用 json.loads 把这个 JSON 转换回字典。

@app.route('/upload', methods=['POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['image']
        f.save('uploads/uploaded_file')
        # do other stuff with values in request.form
        # and return desired output in JSON format
        return jsonify({'success': True})

想了解更多关于文件上传的信息,可以查看 Flask 的 文档

另外,在使用 MultipartEncoder 包含图片时,你需要指定 MIME 类型,同时在请求的头部也要设置内容类型。(我不太确定你是否能用 MultipartEncoder 上传图片,我只成功上传了文本文件。)

m = MultipartEncoder(
    fields={"user_name":"tom", "password":"tom", "method":"login",
            "location":"landing", "cam_id":"c00001", "datetime":"hammaTime!"
            ,'image': ('filename', open('file.txt', 'rb'), 'text/plain')}  # added mime-type here
    )
r = requests.post(url, data=m, headers={'Content-Type': m.content_type})  # added content-type header here
5

你可以在HTTPbin上看到一个可以工作的Flask服务器示例,它可以接受像你想要创建的那种POST请求。如果你做类似这样的事情:

m = MultipartEncoder(fields=your_fields)
r = requests.post('https://httpbin.org/post', data=m, headers={'Content-Type': m.content_type})
print(r.json()['form'])

你会发现你发送的所有内容都应该在那个字典里。

通过使用HTTPBin的源代码,你可以看到

部分是从request.form生成的。你可以用它来获取你其他的数据。然后你可以使用request.files来访问你想上传的图片。

这个Flask路由处理器的示例看起来会像这样:

@app.route('/upload', methods=['POST'])
def upload_files():
    resp = flask.make_response()
    if authenticate_user(request.form):
        request.files['image'].save('path/to/file.jpg')
        resp.status_code = 204
    else:
        resp.status_code = 411
    return resp

不过你应该去看看上传文件的文档。这在使用Flask中的常见模式时非常有用。

撰写回答