Python Flask块数据上传无法正常工作

时间:2017-04-13 04:58:18

标签: python flask request chunks

我正在尝试从客户端(使用Python request.post)将大文件(比如〜1GB)上传到烧瓶服务器。

当客户端以1024的块发送请求到服务器时,服务器不读取整个文件并保存到服务器0kb。

你可以帮我调试我在这里错误的地方。

服务器 - Flask Code:

from flask import Flask, request, jsonify
from werkzeug.utils import secure_filename
import os

app = Flask(__name__)

app.config['UPLOAD_FOLDER'] = 'uploads/'

@app.route("/upload/<filename>", methods=["POST", "PUT"])
def upload_process(filename):
    filename = secure_filename(filename)
    fileFullPath = os.path.join(app.config['UPLOAD_FOLDER'], filename)

    with open(fileFullPath, "wb") as f:
        chunk_size = 1024
        chunk = request.stream.read(chunk_size)
        f.write(chunk)
    return jsonify({'filename': filename})


if __name__ == '__main__':
    app.run(host="0.0.0.0", port=int("8080"),debug=True)

客户 - 请求代码

import os
import requests


def read_in_chunks(file_object, chunk_size=1024):
    while True:
        data = file_object.read(chunk_size)
        if not data:
            break
        yield data


def main(fname, url):
    content_path = os.path.abspath(fname)
    with open(content_path, 'r') as f:
        try:
            r = requests.post(url, data=read_in_chunks(f))
            print "r: {0}".format(r)
        except Exception, e:
            print e


if __name__ == '__main__':
    filename = 'bigfile.zip'  # ~1GB
    url = 'http://localhost:8080/upload/{0}'.format(filename)
    main(filename, url)

3 个答案:

答案 0 :(得分:0)

Flask依靠answer处理流,werkzeug werkzeug。这个demands a content length for a stream上有一个主题,但目前没有真正的解决方案,除了采用另一种框架方法。

答案 1 :(得分:0)

请使用'file.stream.read(chunk_size)'而不是request.stream.read(chunk_size)。它对我有用......!

答案 2 :(得分:0)

下面的示例对所有人都适用。如果您使用Redis,还可以将正在处理的块发布/订阅到另一个API中的进度条中。

from flask import Flask, request, jsonify
@app.route("/submit_vdo", methods=['POST'])
def submit_vdo():

@copy_current_request_context
def receive_chunk(stream, full_file_path):
    if full_file_path is None:
        tmpfile = tempfile.NamedTemporaryFile('wb+', prefix=str(uuid.uuid4())+"_")
        full_file_path = tmpfile.name

    print ('Write temp to ', full_file_path)
    with open(full_file_path, "wb") as f:
        max_chunk_size = settings.VIDEO_MAX_SIZE_CHUNK # config.MAX_UPLOAD_BYTE_LENGHT
        count_chunks = 0
        total_uploaded = 0
        try:
            while True:
                print ('Chunk ', count_chunks)
                chunk = stream.read(max_chunk_size)
                if chunk is not None and len(chunk)>0:
                    total_uploaded += len(chunk)
                    count_chunks += 1
                    f.write(chunk)   
                    temp = {}
                    temp ['chunk_counts'] = count_chunks
                    temp ['total_bytes']  = total_uploaded
                    temp ['status'] = 'uploading...'
                    temp ['success'] = True
                    db_apn_logging.set(user_id+"@CHUNK_DOWNLOAD", json.dumps(temp), ex=5)
                    print (temp)
                else:
                    f.close()
                    temp = {}
                    temp ['chunk_counts'] = count_chunks
                    temp ['total_bytes']  = total_uploaded
                    temp ['status'] = 'DONE'
                    temp ['success'] = True
                    db_apn_logging.set(user_id+"@CHUNK_DOWNLOAD", json.dumps(temp), ex=5)
                    break
        except Exception as e:
            temp = {}
            temp ['chunk_counts'] = count_chunks
            temp ['total_bytes']  = total_uploaded
            temp ['status'] = e
            temp ['success'] = False
            db_apn_logging.set(user_id+"@CHUNK_DOWNLOAD", json.dumps(temp), ex=5)
            return  None

        return full_file_path

    stream = flask.request.files['file']
    stream.seek(0)
    full_file_path = receive_chunk(stream, full_file_path)

    return "DONE !"