私はWPFアプリケーションを持っています。私はそのファイルをソーシャルネットワークの1つに投稿しています。 自分自身をアップロードしても問題ありませんが、アップロードにどれくらいの時間がかかるかを示したいと思います。HTTPの進行状況のアップロード
私はこれを行う方法の束を試してみました:
1)HttpWebRequest.GetStream方法:(はるかに短い)
using (
var FS = File.Open(
localFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
long len = FS.Length;
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
request.Method = "POST";
request.ProtocolVersion = HttpVersion.Version11;
request.ContentType = "multipart/form-data; boundary=--AaB03x";
//predata and postdata is two byte[] arrays, that contains
//strings for MIME file upload (defined above and is not important)
request.ContentLength = predata.Length + FS.Length + postdata.Length;
request.AllowWriteStreamBuffering = false;
using (var reqStream = request.GetRequestStream())
{
reqStream.Write(predata, 0, predata.Length);
int bytesRead = 0;
int totalRead = 0;
do
{
bytesRead = FS.Read(fileData, 0, MaxContentSize);
totalRead += bytesRead;
reqStream.Write(fileData, 0, bytesRead);
reqStream.Flush(); //trying with and without this
//this part will show progress in percents
sop.prct = (int) ((100*totalRead)/len);
} while (bytesRead > 0);
reqStream.Write(postdata, 0, postdata.Length);
}
HttpWebResponse responce = (HttpWebResponse) request.GetResponse();
using (var respStream = responce.GetResponseStream())
{
//do things
}
}
2)Webクライアントの方法:
void UploadFile (url, localFilePath)
{
...
WebClient client = new WebClient();
client.UploadProgressChanged += new UploadProgressChangedEventHandler(UploadPartDone);
client.UploadFileCompleted += new UploadFileCompletedEventHandler(UploadComplete);
client.UploadFileAsync(new Uri(url), localFilePath);
done.WaitOne();
//do things with responce, received from UploadComplete
JavaScriptSerializer jssSer = new JavaScriptSerializer();
return jssSer.Deserialize<UniversalJSONAnswer>(utf8.GetString(UploadFileResponce));
//so on...
...
}
void UploadComplete(object sender, UploadFileCompletedEventArgs e)
{
UploadFileResponce=e.Result;
done.Set();
}
void UploadPartDone(object sender, UploadProgressChangedEventArgs e)
{
//this part expected to show progress
sop.prct=(int)(100*e.BytesSent/e.TotalBytesToSend);
}
3)偶数TcpClient:
using (
var FS = File.Open(
localFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
long len = FS.Length;
long totalRead = 0;
using (var client = new TcpClient(urli.Host, urli.Port))
{
using (var clearstream = client.GetStream())
{
using (var writer = new StreamWriter(clearstream))
using (var reader = new StreamReader(clearstream))
{
//set progress to 0
sop.prct = 0;
// Send request headers
writer.WriteLine("POST " + urli.AbsoluteUri + " HTTP/1.1");
writer.WriteLine("Content-Type: multipart/form-data; boundary=--AaB03x");
writer.WriteLine("Host: " + urli.Host);
writer.WriteLine("Content-Length: " + (predata.Length + len + postdata.Length).ToString());
writer.WriteLine();
//some data for MIME
writer.Write(utf8.GetString(predata));
writer.Flush();
int bytesRead;
do
{
bytesRead = FS.Read(fileData, 0, MaxContentSize);
totalRead += bytesRead;
writer.BaseStream.Write(fileData, 0, bytesRead);
writer.BaseStream.Flush();
sop.prct = (int) ((100*totalRead)/len);
} while (bytesRead > 0)
writer.Write(utf8.GetString(postdata));
writer.Flush();
//read line of response and do other thigs...
respStr = reader.ReadLine();
...
}
}
}
}
すべての場合、ファイルは正常にサーバーに送信されました。 しかし、常に進捗状況は次のようになります。数秒間、0から100まで実行され、ファイルが実際にアップロードされるまで待機します(約5分 - ファイルは400MBです)。
私はファイルからのデータがどこかでバッファリングされていると思うので、私はアップロードではなく、データをバッファリングしています。それがアップロードされるまで待つ必要があります。
私の質問は以下のとおりです。
1)実際アップロードデータを追跡する方法はありますか?メソッドStream.Write()またはFlush()(NetworkStreamのために私がどこかで読んだように動作しない)は、TCPパケットが受信したサーバーからの確認を受け取るまで返されませんでした。
2)または、バッファリングを拒否できますか(AllowWriteStreamBuffering for HttpWebRequestは機能しません)?
3)さらに「下に」進み、ソケットで試してみるのは理にかなっていますか?更新
:
をUIに表示進行の仕方であらゆる疑問を避けるために、私は、ファイルを記録するためのコードを書き直しました。 ので、ここでのコードは次のとおりです。あなたがプログラムは、それが約2秒間〜400メガバイトをアップロードすることを考えて見ることができるように
2011-11-19T22:00:54.5964408+04:00 Start write into request stream.
2011-11-19T22:00:54.6404433+04:00 totalRead= 1048576/410746880
2011-11-19T22:00:54.6424434+04:00 totalRead= 2097152/410746880
2011-11-19T22:00:54.6434435+04:00 totalRead= 3145728/410746880
2011-11-19T22:00:54.6454436+04:00 totalRead= 4194304/410746880
2011-11-19T22:00:54.6464437+04:00 totalRead= 5242880/410746880
2011-11-19T22:00:54.6494438+04:00 totalRead= 6291456/410746880
.......
2011-11-19T22:00:55.3434835+04:00 totalRead= 408944640/410746880
2011-11-19T22:00:55.3434835+04:00 totalRead= 409993216/410746880
2011-11-19T22:00:55.3464837+04:00 totalRead= 410746880/410746880
2011-11-19T22:00:55.3464837+04:00 totalRead= 410746880/410746880
2011-11-19T22:00:55.3464837+04:00 All sent!!! Waiting for responce...
2011-11-19T22:07:23.0616597+04:00 Responce received!
:
using (var LogStream=File.Open("C:\\123.txt",FileMode.Create,FileAccess.Write,FileShare.Read))
using (var LogWriter=new StreamWriter(LogStream))
using (var FS = File.Open(localFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
long len = FS.Length;
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
request.Timeout = 7200000; //2 hour timeout
request.Method = "POST";
request.ProtocolVersion = HttpVersion.Version11;
request.ContentType = "multipart/form-data; boundary=--AaB03x";
//predata and postdata is two byte[] arrays, that contains
//strings for MIME file upload (defined above and is not important)
request.ContentLength = predata.Length + FS.Length + postdata.Length;
request.AllowWriteStreamBuffering = false;
LogWriter.WriteLine(DateTime.Now.ToString("o") + " Start write into request stream. ");
using (var reqStream = request.GetRequestStream())
{
reqStream.Write(predata, 0, predata.Length);
int bytesRead = 0;
int totalRead = 0;
do
{
bytesRead = FS.Read(fileData, 0, MaxContentSize);
totalRead += bytesRead;
reqStream.Write(fileData, 0, bytesRead);
reqStream.Flush(); //trying with and without this
//sop.prct = (int) ((100*totalRead)/len); //this part will show progress in percents
LogWriter.WriteLine(DateTime.Now.ToString("o") + " totalRead= " + totalRead.ToString() + "/" + len.ToString());
} while (bytesRead > 0);
reqStream.Write(postdata, 0, postdata.Length);
}
LogWriter.WriteLine(DateTime.Now.ToString("o") + " All sent!!! Waiting for responce... ");
LogWriter.Flush();
HttpWebResponse responce = (HttpWebResponse) request.GetResponse();
LogWriter.WriteLine(DateTime.Now.ToString("o") + " Responce received! ");
using (var respStream = responce.GetResponseStream())
{
if (respStream == null) return null;
using (var streamReader = new StreamReader(respStream))
{
string resp = streamReader.ReadToEnd();
JavaScriptSerializer jssSer = new JavaScriptSerializer();
return jssSer.Deserialize<UniversalJSONAnswer>(resp);
}
}
}
、ここでは、結果(私は真ん中をカット)です。そして7分後にファイルが実際にアップロードされ、私は応答を受けます。
再び更新:
はこれに思えるは、Windows 7(x64のまたはx86についてSHUREない)の下で起こっています。 コードを実行すると、すべてが正常に動作し、進捗状況が正確に表示されます。
ok。それは妥当と思われる。私は実際にオープンされたフィドラーでテストを行うことができました。 私が家に帰るともう一度チェックします。 – Lumen
私は、フィドラーが、すべての.netネットワーククラスをそうしてはいけないように動作させるいくつかのシステムフックを設定すると思います。 – Vlad
さて、Fiddlerは私が知る限りHTTPプロキシとして募集しています。したがって、宛先ホストに送信される前であっても、自分自身のバッファであり、アップロードホストへのパケットを確認することになります。逆に、Fiddlerを有効にしている間にファイルをダウンロードすると、進行状況は0%にとどまり、その後、ダウンロードされたファイルがプロキシからリクエストを開始したホストにストリーミングされるとすぐに100%にジャンプします。 –