C# 在低内存windows phone设备中使用HttpClient上载大文件的最佳策略是什么?

C# 在低内存windows phone设备中使用HttpClient上载大文件的最佳策略是什么?,c#,.net,windows-phone-8.1,httpclient,C#,.net,Windows Phone 8.1,Httpclient,我试图用类似的方法上传文件 在windows phone中 using (var content = new MultipartFormDataContent()) { content.Add(CreateFileContent(imageStream, "image.jpg", "image/jpeg")); content.Add(CreateFileContent(signatureStream, "image.jpg.sig", "application/octet-st

我试图用类似的方法上传文件 在windows phone中

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;
}
这在上传小文件时效果很好。如果我试图在低端设备(512Mb内存)中上传更大的文件(比如>50mb), 它抛出System.OutOfMemoryException。我使用诊断工具监控内存消耗,并注意到内存 在PostAsync呼叫期间呈指数增长。似乎是将整个内容复制到内存中。目前,我们在应用程序中没有分块支持 api


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

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

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

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

因此,它可能导致for循环遍历块

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

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

也许这样可以解决您的问题:)

手动执行多部分发布-无需
多部分表单数据内容的帮助

如果您必须将其发送到多个部分,那么您可以发布更多内容,从4k缓冲块中读取源文件

您不一定需要使用异步方法来实现这一点。解决方案是“手动控制4k缓冲”。但是异步将是理想的,因为它是线程/CPU效率最高的

下面是另一个推荐链接,以了解如何使用。另一个是为了理解协议,这里有一个示例,说明通过流发送的内容


此外,在架构上,我倾向于将文件单独上传到任何(表单)数据。这完全避免了多部分发布,使API原子化且简单。您可能有一项服务,它可以简单地存储上载的文件并返回URL或ID。然后,该URL或ID可以与您的数据一起引用并随后发布。

除了StreamContent类之外,您还可以使用fileStream:

    using (var fileStream = File.OpenRead(filepath))
    {
       var response = await _httpClient.PostAsync(requestUri, new 
          StreamContent(fileStream)).ConfigureAwait(false);
    }

这似乎完成了在文件中读取和在后台发布的所有必要的分块操作,此外,您还可以根据需要在StreamContent构造函数中设置缓冲区大小。使用这种方法,我没有看到我的应用程序内存占用增长超过1 MB,即使是非常大的文件。

这里有一个解决方案:Windows.Networking.BackgroundTransfer.BackgroundUploader怎么样?请看这里:下载和上传的所有API调用都在SDK中实现(支持.net 4.5.1、Windows Phone 8.1和Windows Store 8.1的可移植类库)。据我所知,PCL中不支持Windows.Networking.BackgroundTransfer.BackgroundUploader,如果我错了,请更正。我必须使用HttpClient实现这一点。我无法控制服务器端api。我正在尝试第二种方法。还尝试使用。该链接与multipart无关,如果从它们的异步体系结构开始,可能会混淆手动实现。您应该从我的链接开始,并从链接中学习如何应用异步方法。有很多方法可以实现手动4k缓冲后多部分流,但我的总体答案基本上是手动执行,并放弃使用MultipartFormDataContent。@Todd为什么不建议使用MultipartFormDataContent?@gusmally抱歉Setomonica-我想我的答案中包含了全部原因。1) 对于客户端和服务器来说,多部分增加了复杂性。复杂性会导致bug和更难维护的代码。2) 在可能的情况下,功能应该只有一个目的。3) 在体系结构上,很容易将文件上载数据与表单数据分离。因此,除非是旧系统的API,或者是新的第三方系统的API,否则没有充分的理由使用多部分API。我无法控制服务器端API。我必须找到一种方法来上传,直到api支持chunked upload.dividedContent,然后像7z multi-Archive一样将其连接在一起?好主意,但还不能尝试