将文件加载为字节数组,而不在内存 C# 中分配它



我正在处理一个端点,以上传文件并将其发送到WCF服务。

我有一个端点,它接受表单数据中的一个文件。用户最多可以上传 50 个文件,但文件会逐个上传(一次上传一个(。每个文件最大为 5MB。因此,在代码中,我将文件读取为 Stream,并且必须将文件作为字节数组发送到 WCF 服务。 这就是问题所在。我不想在内存中分配 5MB 数组只是为了将其发送到 WCF 服务。50 个文件 * 5MB = 250MB。很多。

未优化的代码如下所示。

public async Task<IHttpActionResult> UploadFile()
{
MultipartMemoryStreamProvider multipartMemoryStreamProvider = await Request.Content.ReadAsMultipartAsync();
HttpContent file = multipartMemoryStreamProvider.Contents.GetFormValue("file");
int length = (int) file.Headers.ContentLength;
byte[] fileContent = new byte[length]; // allocating up to 5MB :(
using (Stream stream = await file.ReadAsStreamAsync())
{
await stream.ReadAsync(fileContent, 0, length);
}
await _documentService.UploadAsync("filename", fileContent);
}

我尝试使用ArrayPool,它工作得很好,但是ArrayPool给了我一个具有最少请求字节的数组。因此,我发送了更多我想要的字节(例如,对于 420KB 文件,我收到了 512KB 数组(。我可以使用 ArrayPool.Create((。但是,我不想最终拥有大量的池。

另外,我检查了 Array.Resize (https://learn.microsoft.com/en-us/dotnet/api/system.array.resize?view=netframework-4.8(,但它将元素从旧数组复制到新数组(再次分配相同的数组(。

跨度没有用,因为 .ToArray(( 方法将分配一个新的字节数组。

你知道如何在不分配的情况下创建字节数组吗?

没有办法"在不分配的情况下创建字节数组"。 只要 API 需要数组,就必须创建一个新的数组,因为大小是实例的一部分(您唯一可以做的优化是重用相同大小的数组(。

因此,您的选择是:

  • 忍受它。如果内存分配是一个问题,您可以强制垃圾回收。
  • 将 API 更改为流式处理或支持部分上传,或使用常规 POST 而不是 WCF 方法。

最新更新