在低内存Windows手机设备中使用HttpClient上传大文件的最佳策略是什么?

RP.*_*RP. 10 .net c# httpclient windows-phone-8.1

我正在尝试使用类似方法上传文件HttpClient:如何 在Windows手机中一次上传多个文件.

using (var content = new MultipartFormDataContent())
{
    content.Add(CreateFileContent(imageStream, "image.jpg", "image/jpeg"));
    content.Add(CreateFileContent(signatureStream, "image.jpg.sig", "application/octet-stream"));

    var response = await httpClient.PostAsync(_profileImageUploadUri, content);
    response.EnsureSuccessStatusCode();
}

private StreamContent CreateFileContent(Stream stream, string fileName, string contentType)
{
    var fileContent = new StreamContent(stream);
    fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") 
    { 
        Name = "\"files\"", 
        FileName = "\"" + fileName + "\""
    }; // the extra quotes are key here
    fileContent.Headers.ContentType = new MediaTypeHeaderValue(contentType);            
    return fileContent;
}
Run Code Online (Sandbox Code Playgroud)

这在上传小文件时工作正常.如果我尝试在低端设备(512Mb内存)中上传更大的文件(例如> 50mb),则会抛出System.OutOfMemoryException.我使用诊断工具来监视内存消耗,并注意到在PostAsync调用期间内存会呈指数级增长.似乎它正在将整个内容复制到内存中.现在我们在api中没有分块支持.

在低内存Windows手机设备中使用HttpClient上传大文件的最佳策略是什么?

Tod*_*odd 5

手动执行多部分POST - 没有帮助 MultipartFormDataContent

如果你必须多部分发送它,那么你可以手动发布它,从4k缓冲区块中的源文件中读取.

您不一定需要使用异步方法.解决方案是"手动控制4k缓冲".但异步是理想的,是大多数线程/ CPU效率.

这是另一个推荐的链接,用于了解如何编写多部分帖子.另一个用于理解协议,这是一个通过流发送的内容的示例,说明边界标记

另外,在架构上,我更倾向于将文件分别上传到任何(表单)数据.这样可以完全避免多部分发布,使您的API具有原子性和简单性.您可能拥有一个简单存储上传文件并返回URL或ID的服务.然后,可以使用您的数据引用该URL或ID,然后发布.


Bla*_*z0r 4

我并不是 MultipartFormDataContent 方面的真正专家(它可能会在水下分割内容),但提示可能是分割要发送的数据。

然后发送其他块并在接收端重建它。

例如,将图像分成较小的块(例如 10mb 或更小,具体取决于内存使用情况)并发送这些块

因此它可能会导致 for 循环来遍历块。

foreach (byte[] block in dividedContent)
{
    using (var content = new MultipartFormDataContent())
    {
        content.Add(block);

        var response = await httpClient.PostAsync(_profileImageUploadUri, content);
        response.EnsureSuccessStatusCode();
    }
}
Run Code Online (Sandbox Code Playgroud)

也许类似的东西可以解决你的问题:)