我可以添加PushStreamContent到multipartformdatcontent没有HttpClient缓冲

本文关键字:没有 HttpClient 缓冲 multipartformdatcontent 添加 PushStreamContent 我可以 | 更新日期: 2023-09-27 18:05:14

我试图在HTTP POST中发送一个大文件,以及一些其他数据,使用MultipartFormDataContent。为了以块形式发送文件,我使用PushStreamContent将文件流中的数据块写入输出流,每次写入后刷新:

PushStreamContent pushStreamContent = new PushStreamContent((stream, content, context) => {
    byte[] buffer = new byte[4096];
    int bytesRead;
    do {
        bytesRead = fileStream.Read(buffer, 0, 4096);
        stream.Write(buffer, 0, bytesRead);
        stream.Flush();
    }
    while(bytesRead != 0);
    stream.Close();
});

如果我POST这个HttpContent使用以下代码,一切工作正常:

new HttpClient().PostAsync(destinationUrl, pushStreamContent);

但是,如果将此PushStreamContent添加到MultipartFormDataContent中,则如下所示:

MultipartFormDataContent postForm = new MultipartFormDataContent {
    {stringContent, "atom"},
    {pushStreamContent, "binary"}
};

被发布,然后我在PushStreamContent的lambda内收到OutOfMemoryException。据推测,HttpClient正在将MultipartFormDataContent整个缓冲到内存中,由于请求内容非常大,因此会失败。我希望客户端遵从所包含的PushStreamContent的刷新。这可能吗?我使用的是。net 4.5。

我可以添加PushStreamContent到multipartformdatcontent没有HttpClient缓冲

请求正在被缓冲,因为HttpClient需要知道请求的总长度,以便设置Content-Length报头。PushStreamContent对象对于TryComputeLength(out long)总是返回false。

因此,解决方案是创建PushStreamContent的子类,其中知道其长度:
class PushStreamContentWithLength : PushStreamContent {
    public PushStreamContentWithLength(Action<Stream, HttpContent, TransportContext> onStreamAvailable, long streamLength) : base(onStreamAvailable) {
        mStreamLength = streamLength;
    }
    readonly long mStreamLength;
    protected override bool TryComputeLength(out long length) {
        length = mStreamLength;
        return true;
    }
}

如果将其中一个添加到MultipartFormDataContent中,则在HTTP post期间将数据推送到流,而不是预加载到内存中。