首页 > 解决方案 > 使用发布请求 [python] 将压缩的 numpy 数组(zlib)发送到烧瓶服务器

问题描述

我正在尝试使用 post 请求将压缩numpy数组(用 压缩zlib)发送到烧瓶服务器,但压缩字节对象在服务器端发生了变化。如何正确发送带有requestspost 请求的字节对象,以便我可以在服务器端解压缩?

服务器.py

from flask import Flask
from flask_restful import Resource, Api, reqparse
import json
import numpy as np
import base64


# compression
import zlib

app = Flask(__name__)
api = Api(app)
parser = reqparse.RequestParser()
parser.add_argument('imgb64')

class Predict(Resource):
    def post(self):
        data = parser.parse_args()
        if data['imgb64'] == "":
            return {
                    'data':'',
                    'message':'No file found',
                    'status':'error'
                    }

        img = data['imgb64']

        print('rec')

        # decompress
        print(type(img))
        print(img)

        dec = zlib.decompress(img) # this gives me error



        if img:
            pass

            return json.dumps({
                    'data': 'done', 
                    'message':'darknet processed',
                    'status':'success'
                    })
        return {
                'data':'',
                'message':'Something when wrong',
                'status':'error'
                }


api.add_resource(Predict,'/predict')

if __name__ == '__main__':
    app.run(debug=True, host = '0.0.0.0', port = 5000, threaded=True)

客户端.py

import numpy as np 
import base64
import zlib
import requests

frame = np.random.randint(0,255,(5,5,3)) # dummy rgb image
# compress

data = zlib.compress(frame)
print('b64 encoded')
print(data)
print(len(data))
print(type(data))

r = requests.post("http://127.0.0.1:5000/predict", data={'imgb64' : data}) # sending compressed numpy array

这给了我以下错误:

TypeError: a bytes-like object is required, not 'str'

因此,我尝试将字符串转换为bytes对象:

dec = zlib.decompress(img.encode()) # this gives me error

但是,这也给了我一个错误:

zlib.error: Error -3 while decompressing data: incorrect header check

我尝试了其他编码,它们也失败了。

我注意到的一件事是,当我在客户端打印压缩字节时,它显示:

b'x\x9c-\xcf?J\x82q\x00\x06\xe0\x0ftrVP\\C\xf4\x06\x9268\t\xcdR\x8ej.F\xa0\xe0\xd0\xa6\xa3\xe0V\x07\x10\x1cL\xc8\xd1\x03\xd4\xe4\t\x0c\x12\x84\xb6D\x0c#\xbc\x80O\xf0\x1b\x9e\xf5\xfdS\x89\xa2h\xcf\x9a\x03\xef\xc4\xf8cF\x92\r\xbf4i\x11g\xc83\x0f\x8c\xb9\xa2@\x8e\x1bn\xd91g\xc0\x91%\xd7\xdc\xf3M\x83<i:L\xa8\xf1\x19\xfa\xffw\xfd\xf0\xc5\x94:O\x9cH\x85\xcc6#\x1e\xc3\xf6\x05\xe5\xa0\xc7\x96\x04]J\\\x90\xa1\x1f~Ty\xe1\x8d\x15w|P\xe4\x95K\xb2!\xe3\x0cw)%I'

但在服务器端,接收到的字符串完全不同:

�4ig�3���@�n�1g��%���M�&lt;i:L����w��Ŕ:O�H��6#���ǖ]J\��~Ty�w|P�K�!�w)%I

我还尝试将字节作为字符串发送,通过

r = requests.post("http://127.0.0.1:5000/predict", data={'imgb64' : str(data)})

但是,我无法解压服务器端的数据。

标签: python-3.xflaskzlib

解决方案


看来,我不能zlib直接发送压缩字节,所以我使用base64将数据编码为ascii字符串。

所以,总而言之,这对我有用,numpy数组/任何非字符串数据 -> zlib 压缩 -> base64 编码 -> 发布请求 -> 烧瓶 -> base64 解码 -> zlib 解压缩

客户端.py

import numpy as np 
import base64
import zlib
import requests

frame = np.random.randint(0,255,(5,5,3)) # dummy rgb image

# compress

data = zlib.compress(frame)

data = base64.b64encode(data)


data_send = data

data2 = base64.b64decode(data)

data2 = zlib.decompress(data2)


fdata = np.frombuffer(data2, dtype=np.uint8)

print(fdata)


r = requests.post("http://127.0.0.1:5000/predict", data={'imgb64' : data_send})

服务器.py

from flask import Flask
from flask_restful import Resource, Api, reqparse
import json
import numpy as np
import base64


# compression
import zlib
import codecs


app = Flask(__name__)
api = Api(app)
parser = reqparse.RequestParser()
parser.add_argument('imgb64', help = 'type error')

class Predict(Resource):
    def post(self):
        data = parser.parse_args()
        #print(data)
        if data['imgb64'] == "":
            return {
                    'data':'',
                    'message':'No file found',
                    'status':'error'
                    }

        #img = open(data['imgb64'], 'r').read() # doesn't work
        img = data['imgb64']


        data2 = img.encode()
        data2 = base64.b64decode(data2)

        data2 = zlib.decompress(data2)

        fdata = np.frombuffer(data2, dtype=np.uint8)

        print(fdata)

        if img:

            return json.dumps({
                    'data': 'done', 
                    'message':'darknet processed',
                    'status':'success'
                    })
        return {
                'data':'',
                'message':'Something when wrong',
                'status':'error'
                }


api.add_resource(Predict,'/predict')

if __name__ == '__main__':
    app.run(debug=True, host = '0.0.0.0', port = 5000, threaded=True)

推荐阅读