c# - 文件上传进度

标签 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 应用程序上传文件的进度?

最佳答案

更新:

此控制台应用程序按预期为我工作:

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);
    }

关于c# - 文件上传进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2681573/

相关文章:

c# - 在我的 Controller 中将部分 View 制作为 html "string",用于 json 请求

c# - "ref int m_a"如何让包含m a的对象不被GC回收?

c# - 使用 AOP 打开和关闭与数据库的连接

c# - C# 的动态键是否弃用静态 IOC 模式?

c# - 如何在 C# (Windows phone 7) 中解析 JSON 数组值?

node.js - Nodejs如何处理多张图片上传

php - move_uploaded_file() 无法打开流 : no such file or directory

javascript - 如何使用 blueimp 文件上传插件只上传一次文件?

.net - .NET 3.5 是媒体中心插件的合理先决条件吗?

c# - 多线程,如果一个线程崩溃了应用程序会发生什么