私は .NET 4.0 を使用して、HttpClient が提供する機能を活用しようとしています。目的は、HTTP 動詞「PUT」を使用して、サイズが約 10.5 MB の特定のファイルをリモート サーバーにアップロードすることです。リモート サーバーは node.js を使用します。
小さなコンソール アプリを作成しました (.NET 4.0 フル クライアント プロファイル
ではありません) 使用しているラップトップには .NET 4.5 または Visual Studio 2012
がインストールされていません これらの NuGet パッケージをアプリに追加して、進行状況の更新で非同期アップロード機能を有効にしました
<packages>
<package id="Microsoft.AspNet.WebApi.Client" version="4.0.20710.0" targetFramework="net40" />
<package id="Microsoft.Net.Http" version="2.0.20710.0" targetFramework="net40-Client" />
<package id="Newtonsoft.Json" version="4.5.11" targetFramework="net40" />
</packages>
次に、同期アップロード (UploadFile) を行う単純な関数を作成しました。この関数は期待どおりに機能し、ファイルを正しくアップロードします。
次の UploadFileAsync というメソッドは HttpClient の使用を試み、アップロードの 55 ~ 70% で失敗します。Visual Studio 2010 が一連の例外をスローします。最初のものは通常、次の範囲で異なります
WebException
"The request was aborted: The request was cancelled"
その他様々なタイプに。ただし、2 番目の例外は常に予測可能で同じです。これは
ObjectDisposedExceptoin
Cannot access a disposed object.
Object name: 'System.Net.Sockets.NetworkStream'.
最後に、これはチェーンの最後の例外です
IOException
Unable to read data from the transport connection: Cannot access a disposed object.
Object name: 'System.Net.Sockets.Socket'..
お気づきのとおり、すべての using ブロック、close または dispose ステートメントなどをコードから削除しました。私の人生では、何がうまくいかないのかわかりません!PutAsync と SendAsnyc の両方のメソッドを HttpClient で試しました。唯一の違いは、最初の例外が変更されることです。
コードブロックはこちら
void UploadFile(string fileToUpload)
{
//string fileToUpload = @"F:\\upload_file.txt";
using (FileStream rdr = new FileStream(fileToUpload, FileMode.Open))
{
HttpWebRequest req = null;
Stream reqStream = null;
try
{
req = (HttpWebRequest)WebRequest.Create(url);
req.Method = "PUT";
req.Headers.Add("x-myheader", "163333.zip");
req.ContentType = "application/octet-stream";
req.ContentLength = rdr.Length;
req.AllowWriteStreamBuffering = false;
req.Timeout = 1000000;
reqStream = req.GetRequestStream();
Console.WriteLine(rdr.Length);
byte[] inData = new byte[rdr.Length];
// Get data from upload file to inData
int bytesRead = rdr.Read(inData, 0, (int)rdr.Length);
// put data into request stream
reqStream.Write(inData, 0, (int)rdr.Length);
rdr.Close();
req.GetResponse();
// after uploading close stream
reqStream.Close();
}
catch (Exception e)
{
}
finally
{
rdr.Close();
req.GetResponse();
// after uploading close stream
reqStream.Close();
}
}
}
void UploadFileAsync(string fileToUpload)
{
//string fileToUpload = @"F:\\upload_file.txt";
FileStream rdr = new FileStream(fileToUpload, FileMode.Open, FileAccess.Read, FileShare.Read, 8192, true);
//newfs rdr = new newfs(fileToUpload, FileMode.Open);
HttpClientHandler clientHandler = new HttpClientHandler();
ProgressMessageHandler progressHandler = new ProgressMessageHandler(clientHandler);
HttpClient client = new HttpClient(progressHandler);
try
{
client.DefaultRequestHeaders.Add("x-myheader", "163333.zip");
HttpRequestMessage requestPayLoad = new HttpRequestMessage(HttpMethod.Put, url);
long totalFileSize = rdr.Length;
Console.WriteLine(totalFileSize);
int? previousPercentage = null;
progressHandler.HttpSendProgress += (sender, args) =>
{
if (!previousPercentage.HasValue || previousPercentage != args.ProgressPercentage)
Console.WriteLine(args.ProgressPercentage);
previousPercentage = args.ProgressPercentage;
};
requestPayLoad.Content = new StreamContent(rdr);
//requestPayLoad.Content = new FileContent(fileToUpload);
//var task = client.PutAsync<byte[]>(url, rdr, new BinaryMediaTypeFormatter());
var task = client.SendAsync(requestPayLoad);
task.Wait();
}
catch (Exception e)
{
}
finally
{
//rdr.Close();
client.Dispose();
//req.GetResponse();
//// after uploading close stream
//reqStream.Close();
}
}
アップデート
ファイルがサーバーに正常に到達したようです。これは基本的に、ProgressHandler が誤ったパーセンテージを報告しており、エラーがアップロードの右端にあることを意味します。Fiddler は HTTP 200 ステータス コードを示します。