c# - HttpClient 在上传前读取整个文件。 UWP

标签 c# uwp httpclient portable-class-library dotnet-httpclient

我正在制作一个将文件上传到 facebook 的 UWP 应用程序,我正在使用自定义 HttpContent 以 4k block 的形式上传文件,以最大限度地减少大文件 (>100mb) 的内存使用并报告进度。

我的自定义 HttpContent UploadWithProgressHttpContent:

 class UploadWithProgressHttpContent : HttpContent
{
    private readonly IProgress<OperationProgress> _progress;
    private readonly OperationProgress _data;
    private readonly Stream _file;
    private readonly int _bufferSize;
    private readonly CancellationToken _token;

    public UploadWithProgressHttpContent(
        IProgress<OperationProgress> progress,
    OperationProgress data,
    Stream file,
    int bufferSize,
    CancellationToken token)
{
    _progress = progress;
    _data = data;
    _file = file;
    _bufferSize = bufferSize;
    _token = token;
}



protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
    return CopyStreamWithProgress(_file, stream, _progress, _token, _data, _bufferSize);
}

public static async Task<Stream> CopyStreamWithProgress(
    Stream source,
    Stream destination,
    IProgress<OperationProgress> progress,
    CancellationToken token,
    OperationProgress progressData,
    int bufferSize
    )
{
    int read, offset = 0;
    var buffer = new byte[bufferSize];
    using (source)
    {
        do
        {
            read = await source.ReadAsync(buffer, 0, bufferSize, token);

            await destination.WriteAsync(buffer, 0, read, token);

            offset += read;
            progressData.CurrentSize = offset;
            progress.Report(progressData);
        } while (read != 0);
    }

    return destination;
}
}

我遇到的(使用 fiddler)是整个文件在上传开始之前就被放入内存中(我的进度表甚至在上传开始之前就达到了 100%)。

我确实尝试将 TransferEncodingChunked 设置为 true,并设置文件内容长度,但问题仍然存在。

上传源位于 PCL 内(如果重要的话)。我使用的是最新版本的 System.Net.Http。如果需要,我使用它的方式与在 MediaFire SDK 中使用的方式完全相同

感谢您的帮助。

编辑:添加了 HttpClient 用法:

public async Task<T> Upload<T>(Stream fileStream, string fileName)
{
    var handler = new HttpClientHandler();


    var cli = new HttpClient(handler);

    foreach (var header in Headers)
    {
        cli.DefaultRequestHeaders.Add(header.Key, header.Value);
    }

    var parameters = new MultipartFormDataContent();
    foreach (var parameter in Parameters)
    {
        parameters.Add(new StringContent(parameter.Value), parameter.Key);
    }

    if (fileStream != null)
    {
        var fileContent = new UploadWithProgressHttpContent(ProgressOperation, ProgressData, fileStream,
            _chunkBufferSize, Token, fileStream.Length);

        fileContent.Headers.ContentType = new MediaTypeHeaderValue(MimeTypeHelper.GetMimeType(fileName));
        fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue(StreamParamName);
        fileContent.Headers.ContentDisposition.FileName = fileName;
        fileContent.Headers.ContentLength = fileStream.Length;
        parameters.Add(fileContent, StreamParamName);
    }

    var req = new HttpRequestMessage(method, Path) { Content = parameters };
    if (fileStream != null)
        req.Headers.TransferEncodingChunked = true;


    var completionOption = HttpCompletionOption.ResponseContentRead;


    var resp = await cli.SendAsync(req, completionOption, Token).ConfigureAwait(false);

    return await DeserializeObject<T>(resp);
}

最佳答案

您遇到与量子力学相同的问题 - 观察的行为改变了观察到的。 Fiddler 不支持请求流 - 请参阅 Fiddler makes HttpWebRequest/HttpClient behaviour unexpectedhttp://www.telerik.com/forums/is-it-possible-to-not-buffer-requests

使用 wireshark 我可以看到 block 。

关于c# - HttpClient 在上传前读取整个文件。 UWP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42589784/

相关文章:

c# - Entity Framework 与 ASP.NET 样板的一对一关系

UWP 全屏模式 : how NOT to show taskbar/blue rectangle on mouse move

c - 不属于的随机字节,SSL_read

ios - Angular http 客户端无法在 IOS chrome 浏览器中使用翻译?

c# - 为什么我被迫在未使用的构造函数中引用类型?

c# - Monotouch 的 Pinterest SDK 绑定(bind) - CreatePinWithImageURL 崩溃

c# - UWP C# - 为什么 NotifyPropertyChanged 在这种情况下不触发?

c# - 如何为 gridview 项目(文本 block )提供动态宽度?

java - 为什么将输入读取为流与字符串相比内存效率更高?

c# - (Unity3D) 获取网格系统来检测大于一个图 block 的游戏对象