为了创建非缓冲文件上传,我扩展了 System.Web.Http.WebHost.WebHostBufferPolicySelector,覆盖了本文所述的函数 UseBufferedInputStream():http: //www.strathweb.com/2012/09/dealing -with-large-files-in-asp-net-web-api/。当一个文件被发布到我的控制器时,我可以在跟踪输出中看到被覆盖的函数 UseBufferedInputStream() 肯定会按预期返回 FALSE。但是,使用诊断工具,我可以看到内存随着文件的上传而增长。
在我的自定义 MediaTypeFormatter 中似乎出现了大量内存使用(类似于此处的 FileMediaFormatter:http://lonetechie.com/ )。正是在这个格式化程序中,我想将传入的文件增量写入磁盘,但我还需要解析 json 并使用 Content-Type:multipart/form-data 上传进行一些其他操作。因此,我使用 HttpContent 方法 ReadAsMultiPartAsync(),这似乎是内存增长的来源。我在“等待”之前/之后放置了跟踪输出,看起来当任务阻塞时内存使用量正在迅速增加。
在 ReadAsMultiPartAsync() 返回的部分中找到文件内容后,我将使用 Stream.CopyTo() 将文件内容写入磁盘。这会按预期写入磁盘,但不幸的是,此时源文件已经在内存中。
有人对可能出现的问题有任何想法吗?似乎 ReadAsMultiPartAsync() 正在缓冲整个帖子数据;如果这是真的,为什么我们需要 var fileStream = await fileContent.ReadAsStreamAsync() 来获取文件内容?有没有另一种方法来完成部分的拆分而不将它们读入内存?我的 MediaTypeFormatter 中的代码如下所示:
// save the stream so we can seek/read again later
Stream stream = await content.ReadAsStreamAsync();
var parts = await content.ReadAsMultipartAsync(); // <- memory usage grows rapidly
if (!content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
//
// pull data out of parts.Contents, process json, etc.
//
// find the file data in the multipart contents
var fileContent = parts.Contents.FirstOrDefault(
x => x.Headers.ContentDisposition.DispositionType.ToLower().Trim() == "form-data" &&
x.Headers.ContentDisposition.Name.ToLower().Trim() == "\"" + DATA_CONTENT_DISPOSITION_NAME_FILE_CONTENTS + "\"");
// write the file to disk
using (var fileStream = await fileContent.ReadAsStreamAsync())
{
using (FileStream toDisk = File.OpenWrite("myUploadedFile.bin"))
{
((Stream)fileStream).CopyTo(toDisk);
}
}