在没有 multipart/form-data 的情况下在 Flask 中 ReSTfully 上传文件

ReSTfully upload file in Flask without multipart/form-data

我正在尝试在不使用任何类型 multipart/form-data 的情况下将二进制文件上传到 Flask 端点。我想简单地 POSTPUT 文件中的数据到端点,并将其保存到服务器上的文件中。我能找到的唯一例子,以及其他问题中讨论的唯一方法,使用 multipart/form-data.

以下 "works",但 SHA256 哈希通常不匹配,而上传为 form-data 可以正常工作。

@application.route("/rupload/<filename>", methods=['POST', 'PUT'])
def rupload(filename):
    # Sanity checks and setup skipped.

    filename = secure_filename(filename)
    fileFullPath = os.path.join(UPLOAD_FOLDER, filename)

    with open(fileFullPath, 'wb') as f:
        f.write(request.get_data())

    return jsonify({
        'filename': filename,
        'size': os.path.getsize(fileFullPath)
    })

此外,上面的方法对内存来说效率很低。有没有办法通过某种类型的缓冲流将它写入输出文件?谢谢!

编辑: 我是这样测试的:

curl -v -H 'Content-Type: application/octet-stream' -X POST --data @test.zip https://example.com/test/rupload/test.zip

编辑: --data-binary 没有区别。

问题可能出在您使用的 curl 命令上。手册页推荐--data-binary:"This posts data exactly as specified with no extra processing whatsoever." --data参数是--data-ascii的同义词。可能不需要 -X 参数,因为它应该默认为 POST.

curl -v -H 'Content-Type: application/octet-stream' -X POST --data-binary @test.zip https://example.com/test/rupload/test.zip

request.get_data 调用中还有其他选项可以帮助防止它们在某处被覆盖。但看起来应该在服务器端工作。禁用缓存功能可能对您的用例特别有利。

f.write(request.get_data(cache=False, as_text=False, parse_form_data=False))

如果是服务器端,您可能需要更深入地研究 Werkzeug get_input_stream,它是请求的来源 object。

curl 命令使用 content-type header 作为 'application/octet-stream' 很好。在这种情况下,Flask 似乎没有对此做任何事情,但它可以帮助更普遍地使用代理或其他情况下的数据。

关于高效处理大文件,您可能需要查看 request stream property,get_data 内部使用它来读取数据。

您尝试过使用 hashlib 吗?

import hashlib
...
@application.route("/rupload/<filename>", methods=['POST', 'PUT'])
def rupload(filename):
    # Sanity checks and setup skipped.

    filename = secure_filename(filename)
    fileFullPath = os.path.join(UPLOAD_FOLDER, filename)
    file_hash = hashlib.sha256()
    with open(fileFullPath, 'wb+') as f:
        input = request.get_data()
        f.write(input)
        file_hash.update(input)
        ...
    fileDigest = file_hash.hexdigest()