如何将编码为 JSON 的 Base64 图像从 C# 客户端发送到 Python FastAPI 服务器?

问题描述 投票:0回答:1

我已经成功使用 Python 中的 FastAPI 合并了两个代码。现在的挑战是通过 JSON 发送 Base64 格式的图像进行解释。但是,我遇到了问题,因为 C# 返回 System.Net.WebException:“远程服务器返回错误:(500) 内部服务器错误。”

有什么想法吗?

这是我的代码:
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();
        }
    }
}

我注释掉了几行试图达到预期的结果,但没有成功。

python c# json request fastapi
1个回答
0
投票

问题在于您在服务器端阅读

request
body
的方式。
request.body()
方法返回一个协程,因此,它应该是
await
ed,这意味着端点也应该用
async def
定义——有关def
async def的更多详细信息,请参阅
这个答案
 
端点以及 FastAPI 如何处理它们。示例:

@app.post('/traslape/')
async def traslape(request: Request):
    body = await request.body()
    data = json.loads(body)
    return "whatever"

请注意,由于您要将正文转换为 JSON,因此您可以直接使用以下命令来执行此操作:

data = await request.json()

当您想使用其他(可能更快)JSON 编码器(例如

orjson
)时,自行检索正文然后将其转换为 JSON 非常有用,如这个答案以及这个答案这个答案(当涉及到在 FastAPI 中返回 JSON 数据时,您可能会发现 this 也很有帮助)。

如果您希望使用

def
定义端点,并且仍然能够获取
POST
请求的原始正文,可以在以下答案中找到解决方案:

以同步方式使用FastAPI,如何获取POST请求的原始正文?

演示如何在 FastAPI 中上传/处理 Base64 图像的相关帖子可以在 hereherehere 找到。请注意,您不一定需要在请求正文中将图像作为编码为

application/json
application/x-www-form-urlencoded
的 Base64 字符串发送;您可以将其编码为
multipart/form-data
上传,如 此答案 以及该答案中包含的相关参考文献所示。

© www.soinside.com 2019 - 2024. All rights reserved.