Search code examples
c#asp.net-corexmlhttprequestasp.net-core-6.0

Multipart body length limit 16384 exceeded in NET CORE


What I am trying to do:

I'm trying to access the API in my project (NET Core 6 WebApi) to get data from the response for the project purpose. The API response that I will access is XML data which consists of some data such as title, description, creation date, and also photo data in it. But I get the error Multipart body length limit 16384 exceeded in NET CORE.

Here's how I access the API using IHttpClientFactory in mycontroller:

[Route("Get")]
[HttpGet]
public async Task<IActionResult> Get()
{
   HttpResponseMessage response = await _httpClient.GetAsync('the_name_of_the_api_i_will_be_accessing');
   if (response.IsSuccessStatusCode)
   {
      // Check if the response is multipart/mixed
      var headers = response.Content.Headers;
      if (headers.ContentType?.MediaType == "multipart/mixed")
      {
         // Get the boundary from the content type header
         string boundary = headers.ContentType.Parameters.FirstOrDefault(p => p.Name == "boundary")?.Value ?? "";
         if (string.IsNullOrWhiteSpace(boundary) || (boundary.Length > new FormOptions().MultipartBoundaryLengthLimit))
         {
            throw new InvalidDataException("Boundary is missing or too long.");
         }
         Stream contentStream = await response.Content.ReadAsStreamAsync();
         // Create a new reader based on the boundary
         var reader = new MultipartReader(boundary, contentStream);

         // Start reading sections from the MultipartReader until there are no more
         var section = await reader.ReadNextSectionAsync();
         while (section != null)
         {
            // Check the content type of each section
            var contentType = new ContentType(section.ContentType);
            // Read and process the content of each section based on its content type
            if (contentType.MediaType == "application/xml")
            {
               // This section contains XML data, you can parse and process it as needed
               var xmlContent = await section.ReadAsStringAsync();
               // Process the XML content
            }
            else if (contentType.MediaType == "image/jpeg")
            {
               // This section contains an image (binary data), so i can save it or process it as needed
               using (var imageStream = File.Create("path/to/save/image.jpg"))
               {
                  await section.Body.CopyToAsync(imageStream);
               }
            }
            // Read the next section
            section = await reader.ReadNextSectionAsync();
         }
      }
      return Ok();
   }
   else
   {
      return StatusCode((int)response.StatusCode, "API request failed");
   }
}

Postman Response from the API

<?xml version="1.0" encoding="utf-8"?>
<EventNotificationAlert version="2.0" xmlns="http://www.isapi.org/ver20/XMLSchema">
<dateTime>2023-08-22T09:47:30.486+07:00</dateTime>
<eventState>active</eventState>
<eventDescription>ANPR</eventDescription>
...
</EventNotificationAlert>
-----------------------------7daf10c20d06
Content-Disposition: form-data; name="detectionPicture"; filename="detectionPicture.jpg"
Content-Type: image/jpeg
Content-Length: 548804

Things i've tried:

Actually on this link InvalidDataException: Multipart body length limit 16384 exceeded almost same as mine but the difference is the version of the NET Core that we use and the Content-Type response, which is the Content-Type in the API that I will access in the form of multipart/mixed.

Several problem solving in that link is:

  • Skip view Request.From in Watch or debug quick view [Not working on Me]
  • Increase BodyLengthLimit [Not working on Me]
var builder = WebApplication.CreateBuilder(args);
{
    var services = builder.Services;
    var configuration = builder.Configuration;
    ...

    services.Configure<FormOptions>(x =>
    {
        x.MultipartHeadersLengthLimit = Int32.MaxValue;
        x.MultipartBoundaryLengthLimit = Int32.MaxValue;
        x.MultipartBodyLengthLimit = Int64.MaxValue;
        x.ValueLengthLimit = Int32.MaxValue;
        x.BufferBodyLengthLimit = Int64.MaxValue;
        x.MemoryBufferThreshold = Int32.MaxValue;
    });
}
  • Change http to https or by removing the app.UseHttpsRedirection() in Startup.cs to use http (checked answer) [Sadly, Not working on Me]

Hopefully this is enough information. If not, please let me know what you need and I'd be happy to provide it or test out any suggestions.


Solution

  • Using the ReadAsStreamAsync() function didn't work in my case, so I used another approach which was to read each part of the Content-Type: multipart as a byte using the ReadAsByteArrayAsync() function and then process the bytes with efort because I didn't understand byte calculations before. But that doesn't matter if the results match expectations.

    As a note for people who have the same problem as me, if the response from your multipart is a file data, don't convert it into a string so you can separate each part, although this way will be work and each part can still be separated using the boundary, but the data file in the response will be damaged because it is converted to string and become unreadable, so the solution is to convert it as bytes