You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Tornado中正确收发字节流(含JPG传输场景)

正确在Tornado中收发二进制字节流(以JPG图片为例)

这个问题我之前也踩过坑,核心问题是你把二进制数据当成文本处理了,导致原始字节被不可逆地破坏了。咱们拆解成服务端(Tornado)和客户端(requests)两部分来解决:

问题根源

JPG是二进制文件,不是UTF-8编码的文本。当你用requests.get(url).text接收时,requests会尝试把响应字节按默认编码(通常是UTF-8)解码成字符串——但图片字节里大量存在不符合UTF-8规则的字节,这些字节会被替换成Unicode替换字符�(对应字节\xef\xbf\xbd),之后再转码回去自然和原内容不一样了。


一、Tornado端:正确返回二进制数据

不管是整体返回还是分块发送,核心是告诉客户端“这是二进制数据”,并直接发送原始字节。

1. 整体返回图片字节

直接设置正确的Content-Type,然后用self.write()写入原始字节即可:

import tornado.web
import tornado.ioloop

class ImageHandler(tornado.web.RequestHandler):
    def get(self):
        # 读取原始二进制内容
        with open('file.jpg', 'rb') as f:
            image_content = f.read()
        
        # 告诉客户端这是JPG图片
        self.set_header('Content-Type', 'image/jpeg')
        # 直接发送二进制字节
        self.write(image_content)

# 注册路由并启动服务
app = tornado.web.Application([
    (r'/get-image', ImageHandler),
])

if __name__ == '__main__':
    app.listen(8888)
    tornado.ioloop.IOLoop.current().start()

2. 分块发送字节流

如果需要分块传输(比如大文件),要开启分块编码并逐块flush:

class ChunkedImageHandler(tornado.web.RequestHandler):
    async def get(self):
        self.set_header('Content-Type', 'image/jpeg')
        # 开启分块传输
        self.set_header('Transfer-Encoding', 'chunked')
        
        chunk_size = 1024  # 每次发送1KB块
        with open('file.jpg', 'rb') as f:
            while True:
                chunk = f.read(chunk_size)
                if not chunk:
                    break
                # 写入当前块
                self.write(chunk)
                # 立即刷新缓冲区,发送块到客户端
                await self.flush()
        
        # 结束分块传输
        self.finish()

二、requests端:正确接收二进制数据

绝对不要用.text接收二进制内容,改用.content直接获取原始字节串:

import requests

url = 'http://localhost:8888/get-image'
response = requests.get(url)

# 用.content获取原始二进制字节,和Tornado发送的完全一致
image_bytes = response.content

# 可以验证:把字节写回文件,和原图片完全相同
with open('received_image.jpg', 'wb') as f:
    f.write(image_bytes)

关键总结

  • 服务端(Tornado):返回二进制时必须设置匹配的Content-Type,直接操作原始字节,不要转成字符串;分块发送需开启Transfer-Encoding: chunked并逐块flush。
  • 客户端(requests):二进制内容用.content获取,.text只用于接收文本类响应(比如JSON、HTML)。

内容的提问来源于stack exchange,提问作者user82395214

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:07:33