简体   繁体   中英

Using Python requests for automatic file uploading to Flask environment

I am trying to setup a script where I upload a file (now using the python requests library) to a Flask environment that runs inside of a Docker (-compose) container. The python script is ran in the hypervisor, and I force it to use the same version of python (3.6) as well. I am able to get responses from the server, but the file I upload is 12Kb, and the file the Flask container receives is 2Kb, and I have no clue what is going wrong.

It seems like when I use WireShark to capture the tcp stream, I receive a 2Kb file as well, so my guess the requests library applies some compression, but I can not seem to find any documentation about this happening.

I have tried to replace the file tuple in the sending code with solely the file handle, but this seemed to have no effect. Sending files of a different size results in a different filesize in Flask / Docker. Sending a string instead of the filehandler ("1234567890") results in the filesize being as big as the string length (10 bytes). Replacing the file opening method from rb to r results in a UnicodeDecodeError: 'ascii' codec can't decode byte 0xdf in position 14: ordinal not in range(128) raise inside requests -> encodings .

Hypervisor: send.py

import requests

with open('file.docx', 'rb') as f:
    url = 'http://localhost:8081/file'

    r = requests.post(url, files={'file': ('file', f, 'multipart/form-data')})
    print(r.text)

Flask: file.py

@app.route('/file', methods=['POST'])
def parse_from_post():
    file = request.files['file']
    fn = secure_filename("file.docx") # did this manually instead of getting it from the request for testing reasons
    folder = "/app/files/"
    fl = os.path.join(folder, fn)

    # Removes old file 
    if os.path.exists(fl):
        os.remove(fl)

    file.save(fl)

    return ""

The problem lies with the filesize, which python requests does not take care of directly. I used the MultipartEncoder from the requests_toolbelt package, to encapsulate the file instead of directly plugging in the file in the requests post call.

Hypervisor: send.py

import requests
from requests_toolbelt import MultipartEncoder

with open('file.docx', 'rb') as f:
    url = 'http://localhost:8081/file'
    
    m = MultipartEncoder(fields={
        "file": ("file.docx", f)
    })

    r = requests.post(url, data=m, headers={'Content-Type': m.content_type})
    print(r.text)

I actually found this result from another post on SO , see the first comment on the question linking to https://toolbelt.readthedocs.io/... .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM