Home > Net >  Chunking Files in C# .Net 5
Chunking Files in C# .Net 5

Time:09-25

I have large video files I'm trying to break down into chunks and reassemble on the server side. I've mostly been following the suggestions in this article, but I'm having some issues.

In the code that's bundling up the chunks and sending them across the wire, I have this code:

     using (var client = new HttpClient(clientHandler))
        {
            var requestUri = ApiHelper.GetUrl("api/uploadFile");
            client.BaseAddress = new Uri(requestUri);
            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.Add(Constants.ApiKeyHeaderName, Constants.RoadLivesApiAppKey);

            using (var content = new MultipartFormDataContent())
            {
                var fileBytes = System.IO.File.ReadAllBytes(fileName);
                var fileContent = new ByteArrayContent(fileBytes);
                fileContent.Headers.ContentDisposition = new
                    ContentDispositionHeaderValue("attachment")
                {
                    FileName = Path.GetFileName(fileName)
                };
                content.Add(fileContent);

                try
                {
                    var result = client.PostAsync(requestUri, content).Result;
                    rslt = true;
                }
                catch (Exception ex)
                {
                    rslt = false;
                }
            }
        }

On the server side, I'm trying to get that content back out as a byte array so I can reassemble the file when everything is uploaded. The linked article suggests using Request.Files, which doesn't exist in .NET 5. I've tried utilizing Request.Form.Files, but the whole Request.Form appears empty.

Are there any suggestions for how I can get the ByteArrayContent from the Request object? The Request.ContentLength matches what I expect, but I'm not sure where I can get that data from.

I've tried to get the ByteArrayContent from the Request.Body per the options below but it's not working as expected.

        byte[] bodByteArray;
        MemoryStream ms = new MemoryStream();
        Request.BodyReader.CopyToAsync(ms);
        //Request.Body.CopyToAsync(ms);
        bodByteArray = ms.ToArray();

CodePudding user response:

Everything is much simpler. Here's an example:
Server:

using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace Example.Controllers
{
    [ApiController]
    [Route("api/v1/[controller]")]
    public class UploadController : ControllerBase
    {
        [HttpPost]
        [ProducesResponseType(StatusCodes.Status200OK)]
        public async Task PostAsync(
            CancellationToken cancellationToken = default)
        {
            byte[] bytes;

            // To get bytes, use this code (await is required, you missed it)
            // But I recommend working with Stream in order not to load the server's RAM.
            using (var memoryStream = new MemoryStream())
            {
                await Request.BodyReader.CopyToAsync(memoryStream, cancellationToken).ConfigureAwait(false);
                bytes = memoryStream.ToArray();
            }

            // use bytes here
        }
    }
}

Client:

using System;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace Example.Apis
{
    public partial class ExampleApi
    {
        public async Task UploadAsync(
            string path,
            CancellationToken cancellationToken = default)
        {
            using var client = new HttpClient();

            using var request = new HttpRequestMessage(
                HttpMethod.Post,
                new Uri("https://localhost:5001/api/v1/upload"))
            {
                Content = new StreamContent(File.OpenRead(path)),
            };
            
            using var response = await client.SendAsync(
                request, cancellationToken).ConfigureAwait(false);

            response.EnsureSuccessStatusCode();
        }
    }
}

P.S. In addition to examples, I advise you to learn about Streams as the correct way to work with large files.

  • Related