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

从C#客户端向Python FastAPI发送Base64图片JSON遇500错误

问题描述

我已经完成基于Python FastAPI的代码整合,现在需要通过JSON发送Base64格式图片给后端处理,但C#客户端返回错误:System.Net.WebException: 'The remote server returned an error: (500) Internal Server Error'。以下是我的Python服务端代码和C#客户端代码,求解决思路。

Python服务端代码

import tensorflow as tf
from fastapi import FastAPI
import json
import base64
from PIL import Image
import io
#from flask import request
from fastapi import Request

app = FastAPI()

# Load the saved model
cnn = tf.keras.models.load_model('modelo_cnn.h5')

# Test functions to verify the connection
# @app.get('/prueba0/')
# def prueba0():
#     return "Hello, I'm connecting..."

# Test function to sum two numbers
@app.get('/prueba1/{a}/{b}')
def prueba1(a: int, b: int):
    return a + b

# Test function to display a message
@app.get('/prueba2/{text}')
def prueba2(text: str):
    return "Hello, your message was... " + text

#########################################################################################

# Overlap identification function
@app.post('/traslape/')
def traslape(request: Request):
    global cnn
    
    # Get data from the request body
    body = request.body()
        
    # Decode JSON data
    data = json.loads(body)
    
    # # # Open the JSON file (image)
    # with open(image) as f:
    #      img = json.load(f)
    
    # # Decode the image
    # image = base64.b64decode(img["image"])
    
    # # Open the image from bytes using Pillow
    # image = Image.open(io.BytesIO(image))
    
    # # Concatenate images horizontally
    # #imagen_completa = tf.concat([imagen_i, imagen_d], axis=1)
    
    # # Apply gamma correction to the image
    # gamma = tf.convert_to_tensor(0.6)
    # gamma_corrected = tf.pow(imagen / 255.0, gamma) * 255.0 # imagen_completa
    # image_bw = tf.cast(gamma_corrected, tf.uint8)
    
    # # Convert the image to grayscale
    # grayscale_image = tf.image.rgb_to_grayscale(image_bw)
    
    # # Define new dimensions
    # new_height = 360
    # new_width = 500

    # # Resize the image
    # imagen_completa_resize = tf.image.resize(grayscale_image, [new_height, new_width])
      
    # # Perform classification using the loaded model
    # result = cnn.predict(imagen_completa_resize)
     
    # if result[0][0] > result[0][1]:
    #     result = False # No mask
    # else:
    #     result = True # With mask

    return True

C#客户端代码

using System;
using System.IO;
using System.Net;
using System.Text;

namespace comunica_api
{
    class Program
    {
        static void Main(string[] args)
        {
            // Path to the image in your local file system
            string imagePath = @"C:\Users\VirtualImages[00]20240418_124751_028.jpg";

            try
            {
                // Read the bytes of the image from the file
                byte[] imageBytes = File.ReadAllBytes(imagePath);

                // Convert the bytes to a Base64 formatted string
                string base64String = Convert.ToBase64String(imageBytes);

                // URL of the API
                string url = "http://localhost:8000/traslape/";

                // Data to send
                string json = "{\"image\": \"" + base64String + "\"}";

                // Create the HTTP request
                var request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = "POST"; // Use the POST method 
                request.ContentType = "application/json"; // Set content type as JSON
                request.ContentLength = json.Length;

                // Convert JSON string to bytes
                byte[] jsonBytes = Encoding.UTF8.GetBytes(json);

                // Print the request content before sending it
                Console.WriteLine("Request:");
                Console.WriteLine("URL: " + url);
                Console.WriteLine("Method: " + request.Method);
                Console.WriteLine("Headers:");
                foreach (var header in request.Headers)
                {
                    Console.WriteLine(header.ToString());
                }
                Console.WriteLine("Body:");
                Console.WriteLine(json);


                // Write bytes into the request body using StreamWriter
                using (Stream requestStream = request.GetRequestStream())
                using (StreamWriter writer = new StreamWriter(requestStream))
                {
                    // Write JSON string into the request body
                    writer.Write(json);
                }

                // Send the request and get the response
                
                // HERE IS THE ERROR
                using (var response = (HttpWebResponse)request.GetResponse()) 
                //
                
                {
                    // Read the response from the server
                    using (var streamReader = new StreamReader(response.GetResponseStream()))
                    {
                        // Read the response as a string and display it in the console
                        string responseText = streamReader.ReadToEnd();
                        Console.WriteLine("API Response:");
                        Console.WriteLine(responseText);
                    }
                }
            }
            catch (FileNotFoundException)
            {
                Console.WriteLine("The specified image could not be found.");
            }
            catch (WebException ex)
            {
                // Handle any communication error with the API
                Console.WriteLine("API Communication Error:");
                Console.WriteLine(ex.Message);
            }

            // Wait for the user to press Enter before exiting the program
            Console.ReadLine();
        }
    }
}
解决思路

1. 先定位FastAPI 500错误的具体原因

启动FastAPI服务时用uvicorn main:app --reload,发送请求后查看服务端控制台的异常栈信息,这是找到问题根源最直接的方式。

2. 规范FastAPI请求体解析方式

当前手动用Request对象解析JSON容易出错,改用Pydantic模型接收请求体,自动处理格式校验和解析:

from pydantic import BaseModel

class ImageRequest(BaseModel):
    image: str

@app.post('/traslape/')
def traslape(req: ImageRequest):
    # 直接通过req.image获取Base64字符串
    image_bytes = base64.b64decode(req.image)
    # 后续图像处理逻辑...
    return True

这种写法会在请求体格式错误时返回明确的422错误,而非模糊的500错误。

3. 修复C#端的请求构造问题

  • 避免手动拼接JSON,用序列化框架生成:
    // 定义对应请求结构的类
    public class ImageRequest
    {
        public string image { get; set; }
    }
    
    // 序列化生成JSON(需引用Newtonsoft.Json或System.Text.Json)
    var requestData = new ImageRequest { image = base64String };
    string json = JsonConvert.SerializeObject(requestData);
    
  • 修正ContentLength赋值:当前用json.Length(字符数)错误,应使用UTF8字节数组的长度:
    byte[] jsonBytes = Encoding.UTF8.GetBytes(json);
    request.ContentLength = jsonBytes.Length;
    
  • 直接写入字节流更可靠:替换StreamWriter写法,避免编码不一致问题:
    using (Stream requestStream = request.GetRequestStream())
    {
        requestStream.Write(jsonBytes, 0, jsonBytes.Length);
    }
    

4. 分步测试验证

先简化FastAPI接口,比如只返回Base64字符串的长度,确认C#端能正常发送并接收响应,再逐步添加图像处理和模型预测逻辑,避免一步到位排查困难。

5. 检查模型加载问题

确保modelo_cnn.h5路径正确,启动时添加异常捕获验证模型是否加载成功:

try:
    cnn = tf.keras.models.load_model('modelo_cnn.h5')
except Exception as e:
    print(f"模型加载失败: {e}")
    raise

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 09:31:02