简体   繁体   English

WebClient上传文件错误

[英]WebClient upload file error

I am using VSTS 2008 + C# + .Net 3.5 + ASP.Net + IIS 7.0 to develop a console application at client side to upload a file, and at server side I receive this file using an aspx file. 我正在使用VSTS 2008 + C#+。Net 3.5 + ASP.Net + IIS 7.0在客户端开发控制台应用程序以上传文件,在服务器端我使用aspx文件接收此文件。

From client side, I always notice (from console output) the upload percetage of the file increase from 1% to 50%, then to 100% suddenly. 从客户端,我总是注意到(从控制台输出)文件的上传百分比从1%增加到50%,然后突然增加到100%。 Any ideas what is wrong? 有什么想法有什么不对?

Here is my client side code, 这是我的客户端代码,

class Program
{
    private static WebClient client = new WebClient();
    private static ManualResetEvent uploadLock = new ManualResetEvent(false);

    private static void Upload()
    {
        try
        {
            Uri uri = new Uri("http://localhost/Default.aspx");
            String filename = @"C:\test\1.dat";

            client.Headers.Add("UserAgent", "TestAgent");
            client.UploadProgressChanged += new UploadProgressChangedEventHandler(UploadProgressCallback);
            client.UploadFileCompleted += new UploadFileCompletedEventHandler(UploadFileCompleteCallback);
            client.UploadFileAsync(uri, "POST", filename);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.StackTrace.ToString());
        }
    }

    public static void UploadFileCompleteCallback(object sender, UploadFileCompletedEventArgs e)
    {
        Console.WriteLine("Completed! ");
        uploadLock.Set();
    }

    private static void UploadProgressCallback(object sender, UploadProgressChangedEventArgs e)
    {
        Console.WriteLine (e.ProgressPercentage);
    }

    static void Main(string[] args)
    {
        Upload();

        uploadLock.WaitOne();

        return;
    }
}

Here is my server side code, 这是我的服务器端代码,

    protected void Page_Load(object sender, EventArgs e)
    {
        string agent = HttpContext.Current.Request.Headers["UserAgent"];
        using (FileStream file = new FileStream(@"C:\Test\Agent.txt", FileMode.Append, FileAccess.Write))
        {
            byte[] buf = Encoding.UTF8.GetBytes(agent);
            file.Write(buf, 0, buf.Length);
        }

        foreach (string f in Request.Files.AllKeys)
        {
            HttpPostedFile file = Request.Files[f];
            file.SaveAs("C:\\Test\\UploadFile.dat");
        }
    }

thanks in advance, George 乔治,提前谢谢

This is a known bug in the WebClient class. 这是WebClient类中的已知错误 It will be fixed in .NET 4.0. 它将在.NET 4.0中修复。 Until then you could use HttpWebRequest to implement this functionality. 在此之前,您可以使用HttpWebRequest来实现此功能。


UPDATE: Here's an example of using synchronous HttpWebRequest to upload a file and track the progress: 更新:这是使用同步HttpWebRequest上传文件并跟踪进度的示例:

public sealed class Uploader
{
    public const int CHUNK_SIZE = 1024; // 1 KB

    public void Upload(string url, string filename, Stream streamToUpload, Action<int> progress)
    {
        var request = (HttpWebRequest)WebRequest.Create(url);
        request.Method = "POST";
        string boundary = string.Format("---------------------{0}", DateTime.Now.Ticks.ToString("x"));
        request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
        request.KeepAlive = true;

        using (var requestStream = request.GetRequestStream())
        {
            var header = string.Format("--{0}\r\nContent-Disposition: form-data; name=\"file\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n", boundary, filename);
            var headerBytes = Encoding.ASCII.GetBytes(header);
            requestStream.Write(headerBytes, 0, headerBytes.Length);

            byte[] buffer = new byte[CHUNK_SIZE];
            int bytesRead;
            long total = streamToUpload.Length;
            long totalBytesRead = 0;
            while ((bytesRead = streamToUpload.Read(buffer, 0, buffer.Length)) > 0)
            {
                totalBytesRead += bytesRead;
                progress((int)(100 * totalBytesRead / total));
                byte[] actual = new byte[bytesRead];
                Buffer.BlockCopy(buffer, 0, actual, 0, bytesRead);
                requestStream.Write(actual, 0, actual.Length);
            }
        }
        using (var response = request.GetResponse()) { }
    }
}

class Program
{
    static void Main(string[] args)
    {
        var url = "http://localhost:2141/Default.aspx";
        var filename = "1.dat";
        var uploader = new Uploader();
        using (var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
        {
            uploader.Upload(url, filename, fileStream, progress => Console.WriteLine("{0}% of \"{1}\" uploaded to {2}", progress, filename, url));
        }
    }
}

You can read webclient.UploadProgressChanged code.Then you will know the reason.Code below. 你可以阅读webclient.UploadProgressChanged代码。然后你就会知道原因。下面是代码。

private void PostProgressChanged(AsyncOperation asyncOp, WebClient.ProgressData progress)
  {
      if (asyncOp == null || progress.BytesSent + progress.BytesReceived <= 0L)
          return;
      if (progress.HasUploadPhase)
      {
          int progressPercentage = progress.TotalBytesToReceive >= 0L || progress.BytesReceived != 0L
              ? (progress.TotalBytesToSend < 0L
                  ? 50
                  : (progress.TotalBytesToReceive == 0L
                      ? 100
                      : (int) (50L*progress.BytesReceived/progress.TotalBytesToReceive + 50L)))
              : (progress.TotalBytesToSend < 0L
                  ? 0
                  : (progress.TotalBytesToSend == 0L ? 50 : (int) (50L*progress.BytesSent/progress.TotalBytesToSend)));




          asyncOp.Post(this.reportUploadProgressChanged,
              (object)
                  new UploadProgressChangedEventArgs(progressPercentage, asyncOp.UserSuppliedState,
                      progress.BytesSent, progress.TotalBytesToSend, progress.BytesReceived,
                      progress.TotalBytesToReceive));
      }
      else
      {
          int progressPercentage = progress.TotalBytesToReceive < 0L
              ? 0
              : (progress.TotalBytesToReceive == 0L
                  ? 100
                  : (int) (100L*progress.BytesReceived/progress.TotalBytesToReceive));
          asyncOp.Post(this.reportDownloadProgressChanged,
              (object)
                  new DownloadProgressChangedEventArgs(progressPercentage, asyncOp.UserSuppliedState,
                      progress.BytesReceived, progress.TotalBytesToReceive));
      }
  }

This beheavior is by design, its 50% upload the file and 50% the response of the server. 这种情况是设计的,其50%上传文件和50%的服务器响应。 Not a bug. 不是错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM