如何在Python的http.server中编码二进制响应?发送媒体文件报错求助
解决Python http.server发送二进制文件的UnicodeDecodeError问题
问题原因
出现UnicodeDecodeError是因为打开二进制文件(图片、视频等)时使用了文本模式("r"),文本模式会自动尝试用UTF-8解码文件内容,而二进制文件的字节不符合UTF-8编码规则,导致解码失败。另外代码中还有两个小问题:
mimetypes.guess_type()返回的是元组(如('image/jpeg', None)),直接转字符串会导致Content-Type头格式错误- 对二进制文件内容做了多余的字符串转换,进一步引发编码问题
修复后的代码
from http.server import BaseHTTPRequestHandler, HTTPServer import os.path import mimetypes # 读取配置(原代码保留,若不需要可删除) config = open("config.txt", "r") configlist = config.read().split("__") hostName = "0.0.0.0" serverPort = 8080 class MyServer(BaseHTTPRequestHandler): def do_GET(self): if self.path == "/": # 文本文件用文本模式打开并指定编码 with open("srvf/index.html", "r", encoding="utf-8") as mp: self.send_response(200) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(mp.read().encode("utf-8")) elif os.path.exists("srvf" + self.path): file_path = "srvf" + self.path # 二进制文件用rb模式打开 with open(file_path, "rb") as f: self.send_response(200) # 正确处理MIME类型,取元组第一个元素,默认用二进制流类型 mime_type, _ = mimetypes.guess_type(file_path) content_type = mime_type or "application/octet-stream" self.send_header("Content-type", content_type) self.end_headers() # 直接写入二进制数据,无需转换 self.wfile.write(f.read()) else: with open("error.html", "r", encoding="utf-8") as a: self.send_response(404) self.send_header("Content-type", "text/html") self.end_headers() self.wfile.write(a.read().encode("utf-8")) print(f"error 404 on {self.path}") if __name__ == "__main__": webServer = HTTPServer((hostName, serverPort), MyServer) print(f"Server started http://{hostName}:{serverPort}") try: webServer.serve_forever() except KeyboardInterrupt: pass webServer.server_close() print("Server stopped.")
关键修改点
- 打开文件时区分模式:文本文件(如html)用
"r"并指定编码,二进制文件用"rb"模式 - 正确解析
mimetypes.guess_type()的结果,提取有效的MIME类型 - 二进制文件直接读取字节并写入响应,避免不必要的字符串转换
内容的提问来源于stack exchange,提问作者Zebulun Crenshaw
相关产品推荐
相关产品推荐

