File upload progress

I am trying to track the progress of a file upload, but continue to end up from a dead point (loading from a C # application, not a web page).

I tried using WebClient as such:

 class Program { static volatile bool busy = true; static void Main(string[] args) { WebClient client = new WebClient(); // Add some custom header information client.Credentials = new NetworkCredential("username", "password"); client.UploadProgressChanged += client_UploadProgressChanged; client.UploadFileCompleted += client_UploadFileCompleted; client.UploadFileAsync(new Uri("http://uploaduri/"), "filename"); while (busy) { Thread.Sleep(100); } Console.WriteLine("Done: press enter to exit"); Console.ReadLine(); } static void client_UploadFileCompleted(object sender, UploadFileCompletedEventArgs e) { busy = false; } static void client_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e) { Console.WriteLine("Completed {0} of {1} bytes", e.BytesSent, e.TotalBytesToSend); } } 

The file is downloaded and the progress is printed, but the progress is much faster than the actual download, and when downloading a large file, progress will peak in a few seconds, but the actual download takes several minutes (this is not just waiting for a response, all the data has not yet reached the server).

So I tried to use HttpWebRequest for streaming data (I know that this is not the exact equivalent of loading a file, since it does not create multipart/form-data content, but it serves to illustrate my problem). I set AllowWriteStreamBuffering = false and set ContentLength as suggested by this question / answer :

 class Program { static void Main(string[] args) { FileInfo fileInfo = new FileInfo(args[0]); HttpWebRequest client = (HttpWebRequest)WebRequest.Create(new Uri("http://uploadUri/")); // Add some custom header info client.Credentials = new NetworkCredential("username", "password"); client.AllowWriteStreamBuffering = false; client.ContentLength = fileInfo.Length; client.Method = "POST"; long fileSize = fileInfo.Length; using (FileStream stream = fileInfo.OpenRead()) { using (Stream uploadStream = client.GetRequestStream()) { long totalWritten = 0; byte[] buffer = new byte[3000]; int bytesRead = 0; while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) > 0) { uploadStream.Write(buffer, 0, bytesRead); uploadStream.Flush(); Console.WriteLine("{0} of {1} written", totalWritten += bytesRead, fileSize); } } } Console.WriteLine("Done: press enter to exit"); Console.ReadLine(); } } 

The request does not start until the entire file is written to the stream and already shows full progress at the time of its launch (I use fiddler to check this). I also tried setting SendChunked to true (with and without ContentLength setting). It seems that the data is still cached before being sent over the network.

Is there something wrong with one of these approaches, or maybe there is another way to track the progress of downloading files from a Windows application?

+4
source share
2 answers

Updated:

This console application works for me, as expected:

 static ManualResetEvent done = new ManualResetEvent(false); static void Main(string[] args) { WebClient client = new WebClient(); client.UploadProgressChanged += new UploadProgressChangedEventHandler(client_UploadProgressChanged); client.UploadFileCompleted += new UploadFileCompletedEventHandler(client_UploadFileCompleted); client.UploadFileAsync(new Uri("http://localhost/upload"), "C:\\test.zip"); done.WaitOne(); Console.WriteLine("Done"); } static void client_UploadFileCompleted(object sender, UploadFileCompletedEventArgs e) { done.Set(); } static void client_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e) { Console.Write("\rUploading: {0}% {1} of {2}", e.ProgressPercentage, e.BytesSent, e.TotalBytesToSend); } 
+3
source

I believe your request is being sent over the network. I found that Fiddler 2.3.4.4 does not show partial requests, but MS Network Monitor can show separate packets, but not on localhost loopback (therefore, the server and client must be on different computers if you want to check).

I came across the same hidden buffering issue here and believe that one of the WCF service settings is configured incorrectly on the server for streaming. I'm curious what type of web service you use, bindings, etc. Essentially, the server buffers the entire message and then passes it for processing, so you can see a big delay after sending the last byte from the client.

In the case where I looked where the web service was a REST service for WCF, this file was buffered at the following location before being passed as a stream argument to the web service method:

 C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\86e02ad6\c1702d08\uploads*.post 
+1
source

Source: https://habr.com/ru/post/1307528/


All Articles