“博”技术之精,“客”网络之友。

博,客之博;客,博之客。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

WinForm使用webclient通过http的POST方式上传文件

Posted on 2010-07-06 13:27  nect  阅读(1984)  评论(0编辑  收藏  举报

因项目需要找了很多Winform利用webclient上传文件的方法,但是基本没有太明白,后来经过多方面努力,终于做好了。

背景:C/S结构下用winform想web站点(asp.net)post文件。

服务器:需要一个传统的能post并上传、处理文件的.aspx文件,代码如下:

 

default2.aspx
 1 <%@ page language="C#" autoeventwireup="true" inherits="Default2, App_Web_wnfnivuw" %>
 2 
 3 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 4 
 5 <html xmlns="http://www.w3.org/1999/xhtml" >
 6 <head runat="server">
 7     <title>无标题页</title>
 8 </head>
 9 <body>
10     <form id="form1" runat="server" enctype="multipart/form-data">
11     <div>
12             Specify the file to upload: 
13         <asp:PlaceHolder id="Place" runat="server"> 
14             <input id="File1" type="file" runat="Server"/>
15         </asp:PlaceHolder>
16         <p> 
17         Save as file name (no path): 
18         <input id="Text1" 
19         type="text" 
20         runat="server" /> 
21 
22         <p> 
23         <span id="Span1"
24         style="font: 8pt verdana;" 
25         runat="server" /> 
26 
27         <p> 
28         <input type=button 
29         id="Button1" 
30         value="Upload" 
31         runat="server" onserverclick="Button1_ServerClick" /> 
32     </div>
33     </form>
34 </body>
35 </html>
36 

 

 

网页后台代码:

 

default2.aspx.cs
 1 protected void Page_Load(object sender, EventArgs e)
 2     {
 3         //把request 请求的数据dump 到一个文件中 
 4         if (Page.IsPostBack)
 5         {
 6             byte[] b = Request.BinaryRead(Request.ContentLength);
 7 
 8             FileStream fs = new System.IO.FileStream(@"D:\Log.txt", System.IO.FileMode.Create);             BinaryWriter sw = new System.IO.BinaryWriter(fs);
 9             sw.Write(b);
10             sw.Close();
11             fs.Close();
12         }
13 
14 
15     }

 

 

button的点击:

 

default2.aspx.cs
protected void Button1_ServerClick(object sender, EventArgs e)
    {
        
// Get the HtmlInputFile control from the Controls collection 
        
// of the PlaceHolder control. 
        HtmlInputFile file = (HtmlInputFile)Page.FindControl("File1");

        
// Make sure a file was submitted. 
        
        
if (Text1.Value == "")
        {
            Span1.InnerHtml 
= "Error: you must enter a file name";
            
return;
        }
        
        
// Save file to server. 
        if (file.PostedFile != null)
        {
            
try
            {
                file.PostedFile.SaveAs(
"D:\\" + Text1.Value);
                Span1.InnerHtml 
= "File uploaded successfully to " + "<b>D:\\" + Text1.Value + "</b> on the Web server";
            }
            
catch (Exception exc)
            {
                Span1.InnerHtml 
= "Error saving file <b>D:\\" + Text1.Value + "</b><br>" + exc.ToString();
            }
        } 
    }

 

 

 

C/S客户端“关键”代码:

 

form2.cs
  1         private void btnUpload_Click(object sender, System.EventArgs e)
  2         {
  3             // 非空检验
  4             if (txtAmigoToken.Text.Trim() == "" || txtFilename.Text == "" || txtFileData.Text.Trim() == "")
  5             {
  6                 MessageBox.Show("Please fill data");
  7                 return;
  8             }
  9 
 10             // 所要上传的文件路径
 11             string path = txtFileData.Text.Trim();
 12 
 13             // 检查文件是否存在
 14             if (!File.Exists(path)) 
 15             {
 16                 MessageBox.Show("{0} does not exist!", path);
 17                 return;
 18             }
 19 
 20             // 读文件流
 21             FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
 22             WebClient webClient = new WebClient();
 23 
 24             ///////////////////////////////////////
 25             // 打开页面

 26             ///////////////////////////////////////
 27             byte[] responseData =
 webClient.DownloadData(txtAmigoToken.Text);
 28             string srcString =
 Encoding.UTF8.GetString(responseData);
 29 

 30             ///////////////////////////////////////
 31             // 填写页面并提交

 32             ///////////////////////////////////////
 33 

 34             // 获取页面的 VeiwState                
 35             string viewStateFlag = "id=\"__VIEWSTATE\" value=\"";
 36             int i = srcString.IndexOf(viewStateFlag) + viewStateFlag.Length;
 37             int j = srcString.IndexOf("\"", i);

 38             string viewState = srcString.Substring(i, j - i);
 39 

 40             // 获取页面的 EventValidation                
 41             string eventValidationFlag = "id=\"__EVENTVALIDATION\" value=\"";
 42             i = srcString.IndexOf(eventValidationFlag) + eventValidationFlag.Length;
 43             j = srcString.IndexOf("\"", i);

 44             string eventValidation = srcString.Substring(i, j - i);
 45 

 46             // 获取页面的 EVENTARGUMENT                
 47             string eventargumentFlag = "id=\"__EVENTARGUMENT\" value=\"";
 48             i = srcString.IndexOf(eventargumentFlag) + eventargumentFlag.Length;
 49             j = srcString.IndexOf("\"", i);

 50             string eventargument = "";// srcString.Substring(i, j - i);
 51 

 52             // 获取页面的 EVENTTARGET                
 53             string eventtargetFlag = "id=\"__EVENTTARGET\" value=\"";
 54             i = srcString.IndexOf(eventtargetFlag) + eventtargetFlag.Length;
 55             j = srcString.IndexOf("\"", i);

 56             string eventtarget = "Button1";
 57 
 58             // 这部分需要完善
 59             string ContentType = "application/octet-stream";
 60             byte[] fileBytes = new byte[fs.Length];
 61             fs.Read(fileBytes, 0, Convert.ToInt32(fs.Length));
 62 
 63 
 64             // 生成需要上传的二进制数组
 65             CreateBytes cb = new CreateBytes();
 66             // 所有表单数据
 67             ArrayList bytesArray = new ArrayList();
 68             // 普通表单
 69             bytesArray.Add(cb.CreateFieldData("__EVENTTARGET", eventtarget));
 70             bytesArray.Add(cb.CreateFieldData("__EVENTARGUMENT"
, eventargument));
 71             bytesArray.Add(cb.CreateFieldData("__VIEWSTATE"
, viewState));
 72             bytesArray.Add(cb.CreateFieldData("__EVENTVALIDATION"
, eventValidation));
 73 
 74             bytesArray.Add(cb.CreateFieldData("Text1", txtFilename.Text));
 75             // 文件表单

 76             bytesArray.Add(cb.CreateFieldData("File1", path, ContentType, fileBytes));
 77 
 78             // 合成所有表单并生成二进制数组
 79             byte[] bytes = cb.JoinBytes(bytesArray);
 80 
 81             FileStream fs1 = new System.IO.FileStream(@"F:\PostLog.txt", System.IO.FileMode.Append); //把request 请求的数据dump 到一个文件中 
 82             BinaryWriter sw = new System.IO.BinaryWriter(fs1);
 83             sw.Write(bytes);
 84             sw.Close();
 85             fs1.Close();
 86 
 87             // 返回的内容
 88             byte[] responseBytes;
 89             
 90             // 上传到指定Url
 91             bool uploaded = cb.UploadData(txtAmigoToken.Text, bytes, out responseBytes);
 92 
 93             // 将返回的内容输出到文件
 94             using (FileStream file = new FileStream(@"f:\response.text", FileMode.Create, FileAccess.Write, FileShare.Read))
 95             {
 96                 file.Write(responseBytes, 0, responseBytes.Length);
 97             }
 98 
 99             txtResponse.Text = System.Text.Encoding.UTF8.GetString(responseBytes);
100 
101         }
102 
103         private void btnBrowse_Click(object sender, System.EventArgs e)
104         {
105             if(openFileDialog1.ShowDialog() == DialogResult.OK)
106             {
107                 txtFileData.Text = openFileDialog1.FileName;
108             }
109 
110         }

 

 

CreateBytes类代码:

 

updata.cs
using System;
using System.Web;
using System.IO;
using System.Net;
using System.Text;
using System.Collections;

namespace UploadData.Common
{
    
/**//// <summary>
    
/// 创建WebClient.UploadData方法所需二进制数组
    
/// </summary>
    public class CreateBytes
    {
        Encoding encoding 
= Encoding.UTF8;

        
/**//// <summary>
        
/// 拼接所有的二进制数组为一个数组
        
/// </summary>
        
/// <param name="byteArrays">数组</param>
        
/// <returns></returns>
        
/// <remarks>加上结束边界</remarks>
        public byte[] JoinBytes(ArrayList byteArrays)
        {
            
int length = 0;
            
int readLength = 0;

            
// 加上结束边界
            string endBoundary = Boundary + "--\r\n"//结束边界
            byte[] endBoundaryBytes = encoding.GetBytes(endBoundary);
            byteArrays.Add(endBoundaryBytes);

            
foreach(byte[] b in byteArrays)
            {
                length 
+= b.Length;
            }
            
byte[] bytes = new byte[length];

            
// 遍历复制
            
//
            foreach(byte[] b in byteArrays)
            {
                b.CopyTo(bytes, readLength);
                readLength 
+= b.Length;
            }

            
return bytes;
        }

        
public bool UploadData(string uploadUrl, byte[] bytes, out byte[] responseBytes)
        {
            WebClient webClient 
= new WebClient();
            webClient.Headers.Add(
"Content-Type", ContentType);

            
try
            {
                responseBytes 
= webClient.UploadData(uploadUrl, bytes);
                
return true;
            }
            
catch (WebException ex)
            {
                Stream resp 
= ex.Response.GetResponseStream();
                responseBytes 
= new byte[ex.Response.ContentLength];
                resp.Read(responseBytes, 
0, responseBytes.Length);                
            }
            
return false
        }



        
/**//// <summary>
        
/// 获取普通表单区域二进制数组
        
/// </summary>
        
/// <param name="fieldName">表单名</param>
        
/// <param name="fieldValue">表单值</param>
        
/// <returns></returns>
        
/// <remarks>
        
/// -----------------------------7d52ee27210a3c\r\nContent-Disposition: form-data; name=\"表单名\"\r\n\r\n表单值\r\n
        
/// </remarks>
        public byte[] CreateFieldData(string fieldName, string fieldValue)
        {
            
string textTemplate = Boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}\r\n";
            
string text = String.Format(textTemplate, fieldName, fieldValue);
            
byte[] bytes = encoding.GetBytes(text);
            
return bytes;
        }

        
        
/**//// <summary>
        
/// 获取文件上传表单区域二进制数组
        
/// </summary>
        
/// <param name="fieldName">表单名</param>
        
/// <param name="filename">文件名</param>
        
/// <param name="contentType">文件类型</param>
        
/// <param name="contentLength">文件长度</param>
        
/// <param name="stream">文件流</param>
        
/// <returns>二进制数组</returns>
        public byte[] CreateFieldData(string fieldName, string filename,string contentType, byte[] fileBytes)
        {
            
string end = "\r\n";
            
string textTemplate = Boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
            
            
// 头数据
            string data = String.Format(textTemplate, fieldName, filename, contentType);
            
byte[] bytes = encoding.GetBytes(data);

            

            
// 尾数据
            byte[] endBytes = encoding.GetBytes(end);

            
// 合成后的数组
            byte[] fieldData = new byte[bytes.Length + fileBytes.Length + endBytes.Length];

            bytes.CopyTo(fieldData, 
0); // 头数据
            fileBytes.CopyTo(fieldData, bytes.Length); // 文件的二进制数据
            endBytes.CopyTo(fieldData, bytes.Length + fileBytes.Length); // \r\n

            
return fieldData;
        }

        
#region 属性
        
public string Boundary
        {
            
get 
            {
                
string[] bArray, ctArray;
                
string contentType = ContentType;
                ctArray 
= contentType.Split(';');
                
if (ctArray[0].Trim().ToLower() == "multipart/form-data")
                {
                    bArray 
= ctArray[1].Split('=');
                    
return "--" + bArray[1];
                }
                
return null;
            }
        }

        
public string ContentType
        {
            
get {
                
if (HttpContext.Current == null)
                {
                    
return "multipart/form-data; boundary=---------------------------7d5b915500cee";
                }
                
return HttpContext.Current.Request.ContentType;
            }
        }
        
#endregion
    }
}