通过Flask将numpy数组作为字节从python发送到JS

时间:2019-02-27 06:31:13

标签: javascript python numpy flask data-conversion

一个numpy数组应该通过flask从python发送到JS。我不想对其进行JSON加密并发送,因为它会增加响应的大小,并最终增加响应时间。因此,我认为我可以使用tobytes()将numpy转换为字节,然后通过flask将字节发送给JS,然后再将字节转换回JS中的float值,并发现Converting a string of packed bytes into an array of floats in Javascript答案是有帮助的。

操作列表为

byte_arr = np.array([5.6], dtype=np.float32).tobytes()  # Used one value just to make it simple
return byte_arr  # Bytes can be directly sent from flask as response

在JS中,

str = response.text
bytes = Uint8Array.from(str, c => c.charCodeAt(0))
floats = new Float32Array(bytes.buffer)

但是在JS中转换为float时,我没有得到正确的值。调试时,我发现在JS中,Uint8数组中的某些值与python发送的字节值不匹配。

JS: console.log(bytes)  // [51, 51, 255, 64]
Python: for val in byte_arr: print(val, end=" ")  // 51, 51, 179, 64

为了验证,我在python中创建了另一个客户端,提出了相同的请求,并将响应字节转换为float。我也在这里遇到了同样的问题。因此,我缩小了范围,问题出在服务器端而不是客户端。使用多个值时,我发现另一件有趣的事情是,只有大于127的数字(我想是)才转换为255。

在尝试一些随机破解时,我尝试在发送响应之前使用python的chr()方法将字节整数转换为字符,并且在客户端进行转换。

byte_arr = np.array([5.6], dtype=np.float32).tobytes()
byte_arr_char = "".join([chr(i) for i in byte_arr])
return byte_arr_char

但是我的问题是,这是理想的解决方案,还是我在这里做了一些修改以使其工作?谁能帮助我了解为什么不使用chr()发送纯字节不起作用吗?

1 个答案:

答案 0 :(得分:7)

如果您未明确设置MIME type,我认为Flask会将其视为文本数据。您的浏览器似乎已经用ASCII解码了二进制数据,这可以解释为什么只影响大于127的值。

因此,请尝试在Flask中设置响应的Content-Type

@app.route('/your/url/to/numpy/data')
def get_nparray():
    your_np_array = np.array([5.6], dtype=np.float32)
    response = flask.make_response(your_np_array.tobytes())
    response.headers.set('Content-Type', 'application/octet-stream')
    # response.headers.set('Content-Disposition', 'attachment', filename='np-array.bin')
    return response

或者,有一个辅助函数flask.send_file可以在一行中构造响应。请找到示例here

除此错误外,还要注意二进制数据的endianness,它是特定于硬件的。我会向您介绍此answer Javascript类型的数组和字节序)。