Jef*_*eff 9 c# asp.net azure azure-storage asp.net-web-api
我正在开发一个文件上传经常发生的应用程序,并且可能非常大.
这些文件正在上传到Web API,然后Web API将从请求中获取流,并将其传递给我的存储服务,然后将其上载到Azure Blob存储.
我需要确保:
我看过这篇文章,它描述了如何禁用输入流缓冲,但是许多不同用户的文件上传同时发生,重要的是它实际上完成了它在锡上所说的内容.
这就是我目前控制器中的内容:
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();
}
Run Code Online (Sandbox Code Playgroud)
我不知道如何可靠地测试这个.
编辑:我忘了提到直接上传到Blob存储(绕过我的API)将无法正常工作,因为我正在进行一些大小检查(例如,这个用户可以上传500mb吗?这个用户是否使用了他的配额?).
Jef*_*eff 10
在这个要点的帮助下解决了它.
这是我如何使用它,以及一个聪明的"黑客"来获取实际的文件大小,而不是先将文件复制到内存中.哦,它的速度快了两倍(显然).
// 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;
Run Code Online (Sandbox Code Playgroud)
Voilá,您获得了上传文件的大小,无需将文件复制到Web实例的内存中.
至于在文件上传之前获取文件长度,这并不容易,我不得不采用一些非常令人愉快的方法来获得近似值.
在BlobStorageMultipartStreamProvider:
var approxSize = parent.Headers.ContentLength.Value - parent.Headers.ToString().Length;
Run Code Online (Sandbox Code Playgroud)
这给了我一个非常接近的文件大小,减去了几百个字节(取决于我猜的HTTP头).这对我来说已经足够了,因为我的配额强制执行可以接受削减几个字节.
只是为了炫耀,这是内存占用,由任务管理器中疯狂准确和高级的性能选项卡报告.

