C#在WinForm下使用HttpWebRequest上传文件并显示进度

这段时间因项目需要,要实现WinForm下的文件上传,个人觉得采用FTP方法太麻烦,还得配置FTP服务器,要通过防火墙也是一个麻烦。本来打算采用WebClient方法,但是采用这个方法实现后,进度条很短时间后就达到最大值,要等待一段时间才能传送完毕,要是文件太大(我这里测试约100M),会出现错误。后来才知道,原来WebClient是在加载完整个文件到内存后才真正开始上传,怪不得会出现前面的问题了。不得已参考了很多文章,老外的一个文章对我启发很大(http://blogs.msdn.com/johan/archive/2006/11/15/are-you-getting-outofmemoryexceptions-when-uploading-large-files.aspx),是采用HttpWebRequest方法实现的。废话少说,开始进入正题。实现过程如下:

在WinForm里面调用下面的方法来上传文件:

// <summary>
       /// 将本地文件上传到指定的服务器(HttpWebRequest方法)
       /// </summary>
       /// <paramname="address">文件上传到的服务器</param>
       /// <paramname="fileNamePath">要上传的本地文件(全路径)</param>
       /// <paramname="saveName">文件上传后的名称</param>
       /// <paramname="progressBar">上传进度条</param>
       ///<returns>成功返回1,失败返回0</returns>
       private int Upload_Request(string address, string fileNamePath,string saveName, ProgressBar progressBar)
       {
           int returnValue = 0;

           // 要上传的文件
           FileStream fs = new FileStream(fileNamePath, FileMode.Open,FileAccess.Read);
           BinaryReader r = new BinaryReader(fs);

           //时间戳
           string strBoundary = "----------" +DateTime.Now.Ticks.ToString("x");
           byte[] boundaryBytes = Encoding.ASCII.GetBytes("\r\n--" +strBoundary + "\r\n");

           //请求头部信息
           StringBuilder sb = new StringBuilder();
           sb.Append("--");
           sb.Append(strBoundary);
           sb.Append("\r\n");
           sb.Append("Content-Disposition: form-data; name="");
           sb.Append("file");
           sb.Append(""; filename="");
           sb.Append(saveName);
           sb.Append(""");
           sb.Append("\r\n");
           sb.Append("Content-Type: ");
           sb.Append("application/octet-stream");
           sb.Append("\r\n");
           sb.Append("\r\n");
           string strPostHeader = sb.ToString();
           byte[] postHeaderBytes = Encoding.UTF8.GetBytes(strPostHeader);

           // 根据uri创建HttpWebRequest对象
           HttpWebRequest httpReq = (HttpWebRequest)WebRequest.Create(newUri(address));
           httpReq.Method = "POST";

           //对发送的数据不使用缓存
           httpReq.AllowWriteStreamBuffering = false;

           //设置获得响应的超时时间(300秒)
           httpReq.Timeout = 300000;
           httpReq.ContentType = "multipart/form-data; boundary=" +strBoundary;
           long length = fs.Length + postHeaderBytes.Length +boundaryBytes.Length;
           long fileLength = fs.Length;
           httpReq.ContentLength = length;
           try
           {
               progressBar.Maximum = int.MaxValue;
               progressBar.Minimum = 0;
               progressBar.Value = 0;

               //每次上传4k
               int bufferLength = 4096;
               byte[] buffer = new byte[bufferLength];

               //已上传的字节数
               long offset = 0;

               //开始上传时间
               DateTime startTime = DateTime.Now;
               int size = r.Read(buffer, 0, bufferLength);
               Stream postStream = httpReq.GetRequestStream();

               //发送请求头部消息
               postStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
               while (size > 0)
               {
                   postStream.Write(buffer, 0, size);
                   offset += size;
                   progressBar.Value = (int)(offset * (int.MaxValue / length));
                   TimeSpan span = DateTime.Now - startTime;
                   double second = span.TotalSeconds;
                   lblTime.Text = "已用时:" + second.ToString("F2") + "秒";
                   if (second > 0.001)
                   {
                       lblSpeed.Text = " 平均速度:" + (offset / 1024 /second).ToString("0.00") + "KB/秒";
                   }
                   else
                   {
                       lblSpeed.Text = " 正在连接…";
                   }
                   lblState.Text = "已上传:" + (offset * 100.0 / length).ToString("F2") +"%";
                   lblSize.Text = (offset / 1048576.0).ToString("F2") + "M/" +(fileLength / 1048576.0).ToString("F2") + "M";
                   Application.DoEvents();
                   size = r.Read(buffer, 0, bufferLength);
               }
               //添加尾部的时间戳
               postStream.Write(boundaryBytes, 0, boundaryBytes.Length);
               postStream.Close();

               //获取服务器端的响应
               WebResponse webRespon = httpReq.GetResponse();
               Stream s = webRespon.GetResponseStream();
               StreamReader sr = new StreamReader(s);

               //读取服务器端返回的消息
               String sReturnString = sr.ReadLine();
               s.Close();
               sr.Close();
               if (sReturnString == "Success")
               {
                   returnValue = 1;
               }
               else if (sReturnString == "Error")
               {
                   returnValue = 0;
               }

           }
           catch
           {
               returnValue = 0;
           }
           finally
           {
               fs.Close();
               r.Close();
           }

           return returnValue;
       }

 

参数说明如下:

address:接收文件的URL地址,如:http://localhost/UploadFile/Save.aspx

fileNamePath:要上传的本地文件,如:D:\test.rar

saveName:文件上传到服务器后的名称,如:200901011234.rar

progressBar:显示文件上传进度的进度条。

 

接收文件的WebForm添加一个Save.aspx页面,Load方法如下:

protected void Page_Load(object sender, EventArgs e)
       {
           if (Request.Files.Count > 0)
           {
               try
               {
                   HttpPostedFile file = Request.Files[0];
                   string filePath = this.MapPath("UploadDocument") + "\" +file.FileName;
                   file.SaveAs(filePath);
                   Response.Write("Success\r\n");
               }
               catch
               {
                   Response.Write("Error\r\n");
               }
           }
 

同时需要配置WebConfig文件的httpRuntime 如下:

<httpRuntimemaxRequestLength="102400" executionTimeout="300"/>

不能的话最大只能上传4M了。要是想上传更大的文件,maxRequestLength,executionTimeout设置大些,同时WinForm下的代码行

//设置获得响应的超时时间(300秒)
           httpReq.Timeout = 300000;

也要修改,另外别忘了看看IIS的连接超时是否设置为足够大。

一切都配置好了,运行效果如下:

 

 

为了解决这个问题,我查看了很多文章,记于此,以后遇到同样的问题有个查找的地方。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值