Как читать файл встроенного типа в .Net 8 C#

Я пытаюсь загрузить изображение без имени файла. API получил значение null в параметре файла.

Код отправки запроса (клиентская сторона):

var content = new MultipartFormDataContent
{
    { new StreamContent(file), "file" },
    { new StringContent(JsonConvert.SerializeObject(metadata), Encoding.UTF8, "application/json"), "metadata" }
};

Код получения запроса (API с .Net 8):

     var form = await Request.ReadFormAsync();
     var formFile = form.Files["file"];

//The formFile is returned as NULL

Если я укажу имя файла в содержимом потока, это сработает. Но мое требование - заставить его работать без указания имени файла.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Я нашел решение, нам нужно изменить код API следующим образом:

// Create a minimal API endpoint that handles a POST
// We use the default configured JsonOptions for deserializing the JSON
app.MapPost("/", async (HttpContext ctx, IOptions<JsonOptions> jsonOptions) =>
{
    // make sure we have the correct header type
    if (!MediaTypeHeaderValue.TryParse(ctx.Request.ContentType, out MediaTypeHeaderValue? contentType)
        || !contentType.MediaType.Equals("multipart/form-data", StringComparison.OrdinalIgnoreCase))
    {
        return Results.BadRequest("Incorrect mime-type");
    }

    // Variables for holding the data parsed from the response
    MyData? jsonData = null;
    byte[]? binaryData = null;

    // Get the multipart/form-boundary header from the content-type
    // Content-Type: multipart/form-data; boundary = "--73dc24e0-b350-48f8-931e-eab338df00e1"
    // The spec says 70 characters is a reasonable limit.
    string boundary = GetBoundary(contentType, lengthLimit: 70);
    var multipartReader = new MultipartReader(boundary, ctx.Request.Body);
    
    // Use the multipart reader to read each of the sections
    while (await multipartReader.ReadNextSectionAsync(ct) is { } section)
    {
        // Make sure we have a content-type for the section
        if (!MediaTypeHeaderValue.TryParse(section.ContentType, out MediaTypeHeaderValue? sectionType))
        {
            return Results.BadRequest("Invalid content type in section " + section.ContentType);
        }

        if (sectionType.MediaType.Equals("application/json", StringComparison.OrdinalIgnoreCase))
        {
            // If the section is JSON, deserialize directly from the section stream
            // using the default JSON serialization options configured for the app
            jsonData = await JsonSerializer.DeserializeAsync<MyData>(
                section.Body,
                jsonOptions.Value.JsonSerializerOptions,
                cancellationToken: ctx.RequestAborted);
        }
        else if (sectionType.MediaType.Equals("application/octet-stream", StringComparison.OrdinalIgnoreCase))
        {
            // If the section is binary data, deserialize into an array
            // there are potentially more efficient things we could do here 
            // depending on how you need the data
            using var ms = new MemoryStream();
            await section.Body.CopyToAsync(ms, ctx.RequestAborted);
            binaryData = ms.ToArray();
        }
        else
        {
            return Results.BadRequest("Invalid content type in section " + section.ContentType);
        }
    }

    // Just printing it out for debugging purposes
    app.Logger.LogInformation("Receive Json {JsonData} and binary data {BinaryData}",
        jsonData, Convert.ToBase64String(binaryData));

    return Results.Ok();
    
    // Retrieves the boundary marker from the content-type, handling quotes etc 
    // Taken from https://github.com/dotnet/aspnetcore/blob/4eef6a1578bb0d8a4469779798fe9390543d15c0/src/Http/Http/src/Features/FormFeature.cs#L318-L320
    static string GetBoundary(MediaTypeHeaderValue contentType, int lengthLimit)
    {
        var boundary = HeaderUtilities.RemoveQuotes(contentType.Boundary);
        if (StringSegment.IsNullOrEmpty(boundary))
        {
            throw new InvalidDataException("Missing content-type boundary.");
        }
        if (boundary.Length > lengthLimit)
        {
            throw new InvalidDataException($"Multipart boundary length limit {lengthLimit} exceeded.");
        }
        return boundary.ToString();
    }
});

Источник кода: https://andrewlock.net/reading-json-and-binary-data-from-multipart-form-data-sections-in-aspnetcore/

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