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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 09:04:59