在 C# .Net 5 中分块文件
Chunking Files in C# .Net 5
我有很大的视频文件,我试图分解成块并在服务器端重新组合。我大部分时间都在遵循 this article 中的建议,但我遇到了一些问题。
在捆绑数据块并通过网络发送它们的代码中,我有以下代码:
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;
}
}
}
在服务器端,我正在尝试将该内容作为字节数组取回,以便在上传所有内容后重新组合文件。链接的文章建议使用 Request.Files
,它在 .NET 5 中不存在。我尝试使用 Request.Form.Files
,但整个 Request.Form
显示为空。
对于如何从 Request 对象获取 ByteArrayContent
有什么建议吗? Request.ContentLength
符合我的预期,但我不确定从哪里可以获取该数据。
我已尝试根据以下选项从 Request.Body
中获取 ByteArrayContent
,但它没有按预期工作。
byte[] bodByteArray;
MemoryStream ms = new MemoryStream();
Request.BodyReader.CopyToAsync(ms);
//Request.Body.CopyToAsync(ms);
bodByteArray = ms.ToArray();
一切都简单多了。这是一个例子:
服务器:
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
}
}
}
客户:
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。除了示例,我建议您了解 Streams,这是处理大文件的正确方法。
我有很大的视频文件,我试图分解成块并在服务器端重新组合。我大部分时间都在遵循 this article 中的建议,但我遇到了一些问题。
在捆绑数据块并通过网络发送它们的代码中,我有以下代码:
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;
}
}
}
在服务器端,我正在尝试将该内容作为字节数组取回,以便在上传所有内容后重新组合文件。链接的文章建议使用 Request.Files
,它在 .NET 5 中不存在。我尝试使用 Request.Form.Files
,但整个 Request.Form
显示为空。
对于如何从 Request 对象获取 ByteArrayContent
有什么建议吗? Request.ContentLength
符合我的预期,但我不确定从哪里可以获取该数据。
我已尝试根据以下选项从 Request.Body
中获取 ByteArrayContent
,但它没有按预期工作。
byte[] bodByteArray;
MemoryStream ms = new MemoryStream();
Request.BodyReader.CopyToAsync(ms);
//Request.Body.CopyToAsync(ms);
bodByteArray = ms.ToArray();
一切都简单多了。这是一个例子:
服务器:
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
}
}
}
客户:
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。除了示例,我建议您了解 Streams,这是处理大文件的正确方法。