簡體   English   中英

使用PushStreamContent從HTTPClient上傳

[英]Using PushStreamContent to upload from an HTTPClient

我想客戶端計算機上將大量數據上傳到Web服務器。 我跳到PushStreamContent,所以我可以直接寫到流中,因為結果的大小各不相同,而且可能很大。

流程如下:

User runs query > Reader Ready Event Fires > Begin Upload

觸發ready事件后,偵聽器將其拾取並遍歷結果集,以分段形式上傳數據:

Console.WriteLine("Query ready, uploading");
        byte[] buffer = new byte[1024], form = new byte[200];
        int offset = 0, byteCount = 0;
        StringBuilder rowBuilder = new StringBuilder();
        string builderS;
        var content = new PushStreamContent(async (stream, httpContent, transportContext) =>
        //using (System.IO.Stream stream = new System.IO.FileStream("test.txt", System.IO.FileMode.OpenOrCreate))
        {
            int bytes = 0;
            string boundary = createFormBoundary();
            httpContent.Headers.Remove("Content-Type");
            httpContent.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundary=" + boundary);
            await stream.WriteAsync(form, 0, form.Length);
            form = System.Text.Encoding.UTF8.GetBytes(createFormElement(boundary, "file"));
            await stream.WriteAsync(form, 0, form.Length);
            await Task.Run(async () =>
            {
                foreach (var row in rows)
                {
                    for (int i = 0; i < row.Length; i++)
                    {
                        rowBuilder.Append(row[i].Value);
                        if (i + 1 < row.Length)
                            rowBuilder.Append(',');
                        else
                        {
                            rowBuilder.Append("\r\n");
                        }
                    }
                    builderS = rowBuilder.ToString();
                    rowBuilder.Clear();
                    byteCount = System.Text.Encoding.UTF8.GetByteCount(builderS);
                    bytes += byteCount;
                    if (offset + byteCount > buffer.Length)
                    {
                        await stream.WriteAsync(buffer, 0, offset);
                        offset = 0;
                        if (byteCount > buffer.Length)
                        {
                            System.Diagnostics.Debug.WriteLine("Expanding buffer to {0} bytes", byteCount);
                            buffer = new byte[byteCount];
                        }
                    }
                    offset += System.Text.Encoding.UTF8.GetBytes(builderS, 0, builderS.Length, buffer, offset);
                }
            });
            await stream.WriteAsync(buffer, 0, offset);
            form = System.Text.Encoding.UTF8.GetBytes(boundary);
            await stream.WriteAsync(form, 0, form.Length);
            await stream.FlushAsync(); //pretty sure this does nothing
            System.Diagnostics.Debug.WriteLine("Wrote {0}.{1} megabytes of data", bytes / 1000000, bytes % 1000000);

我認為如果我是服務器,上面的代碼會很好用,只需添加stream.Close(); 將完成它,但是由於我是這里的客戶端,因此將導致錯誤( TaskCancelled )。 我想等待讀取也不會執行任何操作,因為除非我明確關閉流,否則PushStreamContent不會結束請求。 話雖如此,寫入文件將產生我希望上傳的文件,因此一切都能完美寫入。

關於我在這里可以做什么的任何想法? 我可能完全濫用了PushStreamContent但似乎這應該是一個合適的用例。

因此,該解決方案起初有點令人困惑,但它似乎很有意義,而且也許更重要的是,它可行:

using(var content = new MultipartFormDataContent()) 
{
  var pushContent = new PushStreamContent(async (stream, httpContent, transportContext) =>
  { 
    //do the stream writing stuff
    stream.Close();
  });
  content.add(pushContent);
  //post, put, etc. content here
}

之所以PushStreamContent是因為傳遞給PushStreamContent方法的流不是實際的請求流,而是由HttpClient處理的流,就像將文件添加到請求流一樣。 結果,關閉它表示HttpContent這部分輸入的結束,並允許請求完成。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM