文件上传进度

时间:2010-04-21 09:12:44

标签: c# .net-3.5 file-upload progress

我一直在尝试跟踪文件上传的进度,但一直处于死胡同状态(从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应用程序上传文件的进度?

2 个答案:

答案 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