我一直在尝试跟踪文件上传的进度,但一直处于死胡同状态(从C#应用程序而不是网页上传)。
我尝试使用WebClient
:
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);
}
}
文件上传并打印进度但进度比实际上传快得多,上传大文件时进度将在几秒钟内达到最大值但实际上传需要几分钟(不是只是等待响应,所有数据还没有到达服务器。)
所以我尝试使用HttpWebRequest
来传输数据(我知道这不是文件上传的完全等价物,因为它不会产生multipart/form-data
内容,但它确实可以用来说明我的问题) 。我设置AllowWriteStreamBuffering = false
并根据this question/answer:
ContentLength
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();
}
}
在将整个文件写入流并且在启动时已经显示完整进度(我正在使用fiddler进行验证)之前,请求才会开始。我还尝试将SendChunked
设置为true(也可以设置ContentLength
)。看起来数据在通过网络发送之前仍然会被缓存。
其中一种方法是否有问题,或者是否有另一种方法可以跟踪Windows应用程序上传文件的进度?
答案 0 :(得分:3)
<强>更新强>
此控制台应用程序按预期适用于我:
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);
}
答案 1 :(得分:1)
我相信您的 请求通过网络传输。我发现Fiddler 2.3.4.4没有显示部分请求,但MS Network Monitor可以显示单个数据包,但不会显示在localhost环回上(因此如果您想验证,服务器和客户端需要在不同的机器上)。
我遇到了相同的隐藏缓冲问题here并且认为其中一个WCF服务设置未在服务器上正确设置以进行流式传输。我很好奇你正在实现什么类型的Web服务,绑定等。本质上,服务器缓冲整个消息,然后将其交给处理,这就是为什么在客户端发送最后一个字节后可能会看到很大的延迟。
对于我正在查看Web服务是WCF REST服务的情况,该文件在作为流参数传递给Web服务方法之前在以下位置进行缓冲:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files\root\86e02ad6\c1702d08\uploads*.post