gpt4 book ai didi

c# - 如何在没有临时文件的情况下将流从 Web API 传递到 Azure Blob 存储?

转载 作者:太空狗 更新时间:2023-10-29 17:39:05 24 4
gpt4 key购买 nike

我正在开发一个经常发生文件上传的应用程序,并且文件大小可能非常大。

这些文件正在上传到 Web API,然后 Web API 将从请求中获取流,并将其传递到我的存储服务,然后将其上传到 Azure Blob 存储。

我需要确保:

  • Web API 实例上未写入任何临时文件
  • 请求流在传递到存储服务之前未完全读入内存(以防止 OutOfMemoryExceptions)。

我看过this article ,它描述了如何禁用输入流缓冲,但由于来自许多不同用户的许多文件上传同时发生,因此重要的是它实际上按照其说明进行操作。

这是我目前 Controller 中的内容:

if (this.Request.Content.IsMimeMultipartContent())
{
var provider = new MultipartMemoryStreamProvider();
await this.Request.Content.ReadAsMultipartAsync(provider);
var fileContent = provider.Contents.SingleOrDefault();

if (fileContent == null)
{
throw new ArgumentException("No filename.");
}

var fileName = fileContent.Headers.ContentDisposition.FileName.Replace("\"", string.Empty);

// I need to make sure this stream is ready to be processed by
// the Azure client lib, but not buffered fully, to prevent OoM.
var stream = await fileContent.ReadAsStreamAsync();
}

我不知道如何可靠地测试它。

编辑:我忘了提及直接上传到 Blob 存储(绕过我的 API)是行不通的,因为我正在做一些大小检查(例如,这个用户可以上传 500mb 吗?这个用户有用了他的配额?)。

最佳答案

this Gist 的帮助下解决了这个问题.

以下是我如何使用它,以及一个巧妙的“黑客”来获取实际文件大小,而无需先将文件复制到内存中。哦,速度快了一倍(显然)。

// Create an instance of our provider.
// See https://gist.github.com/JamesRandall/11088079#file-blobstoragemultipartstreamprovider-cs for implementation.
var provider = new BlobStorageMultipartStreamProvider ();

// This is where the uploading is happening, by writing to the Azure stream
// as the file stream from the request is being read, leaving almost no memory footprint.
await this.Request.Content.ReadAsMultipartAsync(provider);

// We want to know the exact size of the file, but this info is not available to us before
// we've uploaded everything - which has just happened.
// We get the stream from the content (and that stream is the same instance we wrote to).
var stream = await provider.Contents.First().ReadAsStreamAsync();

// Problem: If you try to use stream.Length, you'll get an exception, because BlobWriteStream
// does not support it.

// But this is where we get fancy.

// Position == size, because the file has just been written to it, leaving the
// position at the end of the file.
var sizeInBytes = stream.Position;

瞧,您无需将文件复制到 Web 实例的内存中即可获取上传文件的大小。

至于在文件上传之前获取文件长度,这并不容易,我不得不求助于一些相当不愉快的方法才能获得近似值。

BlobStorageMultipartStreamProvider中:

var approxSize = parent.Headers.ContentLength.Value - parent.Headers.ToString().Length;

这给了我一个非常接近的文件大小,少了几百个字节(我猜这取决于 HTTP header )。这对我来说已经足够了,因为我的配额强制可以接受被削减的几个字节。

仅供炫耀,这里是内存占用情况,由任务管理器中极其准确且先进的性能选项卡报告。

Before - 使用MemoryStream,在上传之前将其读入内存

Before

之后 - 直接写入 Blob 存储

After

关于c# - 如何在没有临时文件的情况下将流从 Web API 传递到 Azure Blob 存储?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30031452/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com