我可以将 PushStreamContent 添加到 MultipartFormDataContent 而不需要 HttpClient 缓冲整个请求吗?

And*_*net 2 .net c# post multipartform-data dotnet-httpclient

我正在尝试使用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();
});
Run Code Online (Sandbox Code Playgroud)

如果我HttpContent使用以下代码发布此内容,则一切正常:

new HttpClient().PostAsync(destinationUrl, pushStreamContent);
Run Code Online (Sandbox Code Playgroud)

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

MultipartFormDataContent postForm = new MultipartFormDataContent {
    {stringContent, "atom"},
    {pushStreamContent, "binary"}
};
Run Code Online (Sandbox Code Playgroud)

并将发布,然后我OutOfMemoryException在 的 lambda 内收到一个PushStreamContent。据推测,它HttpClient正在将整个数据缓冲MultipartFormDataContent到内存中,但由于请求内容非常大,因此失败。我希望客户能够推迟所包含的内容的冲洗PushStreamContent。这可能吗?我正在使用.NET 4.5。

And*_*net 5

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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