Python无框架Web API上传图片存储后无法打开问题求助
问题描述
用Python原生http.server搭建了一个Web API,目标是通过POST(兼容GET)请求上传图片并存储到本地。目前能成功保存图片,且文件大小和原图一致,但保存后的图片无法打开。
相关代码
API代码
import os import shutil from http.server import BaseHTTPRequestHandler, HTTPServer import json class RequestHandler(BaseHTTPRequestHandler): def _set_cors_headers(self): self.send_header("Access-Control-Allow-Origin", "*") self.send_header("Access-Control-Allow-Methods", "GET, POST, OPTIONS") self.send_header("Access-Control-Allow-Headers", "Content-Type") def do_OPTIONS(self): self.send_response(200) self._set_cors_headers() self.end_headers() def do_POST(self): if self.path == '/predict': content_length = int(self.headers['Content-Length']) file_data = self.rfile.read(content_length) filename = self.headers.get('filename', 'image.jpg') save_path = f'./yolov5/data/images/{filename}' with open(save_path, 'wb') as f: f.write(file_data) self.send_response(200) self.end_headers() else: self.send_response(404) self.end_headers() def do_GET(self): if self.path == '/': self.send_response(200) self.send_header('Content-type', 'application/json') self.end_headers() response_data = { 'Hello': 'World' } response_json = json.dumps(response_data) self.wfile.write(response_json.encode()) else: self.send_response(404) self.end_headers() def run_server(): host = '127.0.0.1' port = 8000 server_address = (host, port) httpd = HTTPServer(server_address, RequestHandler) print(f'Starting server on {host}:{port}...') httpd.serve_forever() if __name__ == '__main__': run_server()
Python POST请求代码
import requests url = 'http://127.0.0.1:8000/predict' files = {'image': open('D:/image.jpg', 'rb')} res = requests.post(url, files=files) print(res)
Dart POST请求代码
import 'dart:typed_data'; import 'package:http/http.dart' as http; import 'dart:async'; import 'dart:io'; void some() async { final url = Uri.parse('http://127.0.0.1:8000/predict'); final request = http.MultipartRequest('POST', url); request.files.add(await http.MultipartFile.fromPath('image', "D:/img.jpg")); final response = await request.send(); print(response); } void main() { some(); }
问题原因
你用requests或Dart的MultipartRequest发送的是multipart/form-data格式的请求,这种请求包含表单边界、字段描述头等额外信息。当前API代码直接读取并保存了整个请求体,导致保存的文件不是纯图片字节,而是混杂了这些额外数据,因此图片损坏无法打开。
解决方法
修改API的do_POST方法,解析multipart/form-data请求,提取出图片的原始数据。可以使用Python内置的cgi模块来处理:
修改后的API代码(仅替换do_POST部分,其余代码保持不变):
import cgi # 新增导入 def do_POST(self): if self.path == '/predict': # 解析multipart/form-data请求 form = cgi.FieldStorage( fp=self.rfile, headers=self.headers, environ={'REQUEST_METHOD': 'POST', 'CONTENT_TYPE': self.headers['Content-Type']} ) # 获取上传的文件字段 file_item = form.getvalue('image') if not file_item: self.send_response(400) self.end_headers() self.wfile.write(b'Missing image file') return # 获取文件名,优先用上传文件的原始文件名,否则用默认值 filename = form['image'].filename if 'image' in form and hasattr(form['image'], 'filename') else 'image.jpg' save_path = f'./yolov5/data/images/{filename}' # 保存纯图片数据 with open(save_path, 'wb') as f: f.write(file_item) self.send_response(200) self._set_cors_headers() # 新增CORS头,避免跨域问题 self.end_headers() self.wfile.write(b'Image saved successfully') else: self.send_response(404) self.end_headers()
说明
- 新增
cgi模块导入,用于解析multipart/form-data格式的请求 - 通过
cgi.FieldStorage提取出image字段对应的纯图片字节数据 - 优先使用上传文件的原始文件名,提升可用性
- 增加了错误处理(如缺少图片字段时返回400)
- 在响应中添加CORS头,避免前端跨域请求报错
内容的提问来源于stack exchange,提问作者Muthu Vijay
相关产品推荐
相关产品推荐

