Как отправить изображение Base64, закодированное как JSON, из клиента C# на сервер Python FastAPI?

Мне удалось объединить два кода с помощью FastAPI в Python. Теперь задача заключается в отправке изображения в формате Base64 через JSON для интерпретации. Однако я столкнулся с проблемами, поскольку C# возвращается System.Net.WebException: 'The remote server returned an error: (500) Internal Server Error'.

Есть идеи?

Вот мои коды:
Питон

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

С#

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();
        }
    }
}

В качестве примечания: не следует передавать изображения через base64. Этот формат имеет накладные расходы размером 4/3. Для небольших двоичных файлов это нормально, но изображения обычно слишком велики, чтобы их можно было игнорировать.

freakish 20.04.2024 12:56

найдите UploadFile для FastAPI

Zwick Vitaly 05.05.2024 13:38
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
136
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема в том, как вы читаете requestbody на стороне сервера. Метод request.body() возвращает сопрограмму , поэтому ее следует await использовать, а это означает, что конечная точка также должна быть определена с помощью 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 полезно, если вы хотите использовать другие (возможно, более быстрые) кодировщики JSON, например orjson, как показано в этом ответе , а также этом ответе и ️ 🔁 этот ответ (вы также можете найти это полезным, когда дело доходит до возврата данных JSON в FastAPI).

Если вы хотите, чтобы конечная точка была определена с помощью def, но при этом иметь возможность получать необработанное тело запроса POST, решения можно найти в следующем ответе:

Используя FastAPI для синхронизации, как я могу получить необработанное тело запроса POST?

Похожие сообщения, демонстрирующие, как загружать/работать с изображениями base64 в FastAPI, можно найти здесь , а также здесь и здесь . Обратите внимание, что вам не обязательно отправлять изображение в виде строки base64, закодированной как application/json или application/x-www-form-urlencoded в теле запроса; вместо этого вы можете загрузить его в кодировке multipart/form-data, как показано в этом ответе, и соответствующие ссылки включены в этот ответ.

Это работает для меня, большое спасибо :)

zumbide123 21.06.2024 00:35

Другие вопросы по теме