假如某网站有个表单,例如(url:http://localhost/login.aspx):
帐号
密码
我们需要在程序中提交数据到这个表单,对于这种表单,我们可以使用WebClient.UploadData方法来实现,将所要上传的数据拼成字符即可,程序很简单:
stringuriString="http://localhost/login.aspx";
//创建一个新的WebClient实例.
WebClientmyWebClient=newWebClient();
stringpostData="Username=admin&Password=admin";
//注意这种拼字符串的ContentType
myWebClient.Headers.Add("Content-Type","application/x-www-form-urlencoded");
//转化成二进制数组
byte[]byteArray=Encoding.ASCII.GetBytes(postData);
//上传数据,并获取返回的二进制数据.
byte[]responseArray=myWebClient.UploadData(uriString,"POST",byteArray);
对于文件上传类的表单,例如(url:http://localhost/uploadFile.aspx):
文件
对于这种表单,我们可以使用
StringuriString="http://localhost/uploadFile.aspx";
//创建一个新的WebClient实例.
WebClientmyWebClient=newWebClient();
stringfileName=@"C:upload.txt";
//直接上传,并获取返回的二进制数据.
byte[]responseArray=myWebClient.UploadFile(uriString,"POST",fileName);
还有一种表单,不仅有文字,还有文件,例如(url:http://localhost/uploadData.aspx):
文件名
文件
对于这种表单,似乎前面的两种方法都不能适用,对于第一种方法,不能直接拼字符串,对于第二种,我们只能传文件,重新回到第一个方法,注意参数:
publicbyte[]UploadData(
stringaddress,
stringmethod,
byte[]data
);
在第一个例子中,是通过拼字符串来得到byte[]data参数值的,对于这种表单显然不行,反过来想想,对于uploadData.aspx这样的程序来说,直接通过网页提交数据,后台所获取到的流是什么样的呢?(在我以前的一篇blog中,曾分析过这个问题:asp无组件上传进度条解决方案),最终的数据如下:
-----------------------------7d429871607fe
Content-Disposition:form-data;name="file1";filename="G:homepage.txt"
Content-Type:text/plain
宝玉:http://www.webuc.net
-----------------------------7d429871607fe
Content-Disposition:form-data;name="filename"
defaultfilename
-----------------------------7d429871607fe--
所以只要拼一个这样的byte[]data数据Post过去,就可以达到同样的效果了。但是一定要注意,对于这种带有文件上传的,其ContentType是不一样的,例如上面的这种,其ContentType为"multipart/form-data;boundary=---------------------------7d429871607fe"。有了ContentType,我们就可以知道boundary(就是上面的"---------------------------7d429871607fe"),知道boundary了我们就可以构造出我们所需要的byte[]data了,最后,不要忘记,把我们构造的ContentType传到WebClient中(例如:webClient.Headers.Add("Content-Type",ContentType);)这样,就可以通过WebClient.UploadData方法上载文件数据了。
具体代码如下:
生成二进制数据类的封装
usingSystem;
usingSystem.Web;
usingSystem.IO;
usingSystem.Net;
usingSystem.Text;
usingSystem.Collections;
namespaceUploadData.Common
...{
/**////<summary>
///创建WebClient.UploadData方法所需二进制数组
///</summary>
publicclassCreateBytes
...{
Encodingencoding=Encoding.UTF8;
/**////<summary>
///拼接所有的二进制数组为一个数组
///</summary>
///<paramname="byteArrays">数组</param>
///<returns></returns>
///<remarks>加上结束边界</remarks>
publicbyte[]JoinBytes(ArrayListbyteArrays)
...{
intlength=0;
intreadLength=0;
//加上结束边界
stringendBoundary=Boundary+"--rn";//结束边界
byte[]endBoundaryBytes=encoding.GetBytes(endBoundary);
byteArrays.Add(endBoundaryBytes);
foreach(byte[]binbyteArrays)
...{
length+=b.Length;
}
byte[]bytes=newbyte[length];
//遍历复制
//
foreach(byte[]binbyteArrays)
...{
b.CopyTo(bytes,readLength);
readLength+=b.Length;
}
returnbytes;
}
publicboolUploadData(stringuploadUrl,byte[]bytes,outbyte[]responseBytes)
...{
WebClientwebClient=newWebClient();
webClient.Headers.Add("Content-Type",ContentType);
try
...{
responseBytes=webClient.UploadData(uploadUrl,bytes);
returntrue;
}
catch(WebExceptionex)
...{
Streamresp=ex.Response.GetResponseStream();
responseBytes=newbyte[ex.Response.ContentLength];
resp.Read(responseBytes,0,responseBytes.Length);
}
returnfalse;
}
/**////<summary>
///获取普通表单区域二进制数组
///</summary>
///<paramname="fieldName">表单名</param>
///<paramname="fieldValue">表单值</param>
///<returns></returns>
///<remarks>
///-----------------------------7d52ee27210a3crnContent-Disposition:form-data;name="表单名"rnrn表单值rn
///</remarks>
publicbyte[]CreateFieldData(stringfieldName,stringfieldValue)
...{
stringtextTemplate=Boundary+"rnContent-Disposition:form-data;name="{0}"rnrn{1}rn";
stringtext=String.Format(textTemplate,fieldName,fieldValue);
byte[]bytes=encoding.GetBytes(text);
returnbytes;
}
/**////<summary>
///获取文件上传表单区域二进制数组
///</summary>
///<paramname="fieldName">表单名</param>
///<paramname="filename">文件名</param>
///<paramname="contentType">文件类型</param>
///<paramname="contentLength">文件长度</param>
///<paramname="stream">文件流</param>
///<returns>二进制数组</returns>
publicbyte[]CreateFieldData(stringfieldName,stringfilename,stringcontentType,byte[]fileBytes)
...{
stringend="rn";
stringtextTemplate=Boundary+"rnContent-Disposition:form-data;name="{0}";filename="{1}"rnContent-Type:{2}rnrn";
//头数据
stringdata=String.Format(textTemplate,fieldName,filename,contentType);
byte[]bytes=encoding.GetBytes(data);
//尾数据
byte[]endBytes=encoding.GetBytes(end);
//合成后的数组
byte[]fieldData=newbyte[bytes.Length+fileBytes.Length+endBytes.Length];
bytes.CopyTo(fieldData,0);//头数据
fileBytes.CopyTo(fieldData,bytes.Length);//文件的二进制数据
endBytes.CopyTo(fieldData,bytes.Length+fileBytes.Length);//rn
returnfieldData;
}
属性#region属性
publicstringBoundary
...{
get
...{
string[]bArray,ctArray;
stringcontentType=ContentType;
ctArray=contentType.Split(';');
if(ctArray[0].Trim().ToLower()=="multipart/form-data")
...{
bArray=ctArray[1].Split('=');
return"--"+bArray[1];
}
returnnull;
}
}
publicstringContentType
...{
get...{
if(HttpContext.Current==null)
...{
return"multipart/form-data;boundary=---------------------------7d5b915500cee";
}
returnHttpContext.Current.Request.ContentType;
}
}
#endregion
}
}
在Winform中调用
usingSystem;
usingSystem.Drawing;
usingSystem.Collections;
usingSystem.ComponentModel;
usingSystem.Windows.Forms;
usingSystem.Data;
usingUploadData.Common;
usingSystem.IO;
namespaceUploadDataWin
...{
/**////<summary>
///frmUpload的摘要说明。
///</summary>
publicclassfrmUpload:System.Windows.Forms.Form
...{
privateSystem.Windows.Forms.LabellblAmigoToken;
privateSystem.Windows.Forms.TextBoxtxtAmigoToken;
privateSystem.Windows.Forms.LabellblFilename;
privateSystem.Windows.Forms.TextBoxtxtFilename;
privateSystem.Windows.Forms.ButtonbtnBrowse;
privateSystem.Windows.Forms.TextBoxtxtFileData;
privateSystem.Windows.Forms.LabellblFileData;
privateSystem.Windows.Forms.ButtonbtnUpload;
privateSystem.Windows.Forms.OpenFileDialogopenFileDialog1;
privateSystem.Windows.Forms.TextBoxtxtResponse;
/**////<summary>
///必需的设计器变量。
///</summary>
privateSystem.ComponentModel.Containercomponents=null;
publicfrmUpload()
...{
//
//Windows窗体设计器支持所必需的
//
InitializeComponent();
//
//TODO:在InitializeComponent调用后添加任何构造函数代码
//
}
/**////<summary>
///清理所有正在使用的资源。
///</summary>
protectedoverridevoidDispose(booldisposing)
...{
if(disposing)
...{
if(components!=null)
...{
components.Dispose();
}
}
base.Dispose(disposing);
}
Windows窗体设计器生成的代码#regionWindows窗体设计器生成的代码
/**////<summary>
///设计器支持所需的方法-不要使用代码编辑器修改
///此方法的内容。
///</summary>
privatevoidInitializeComponent()
...{
this.lblAmigoToken=newSystem.Windows.Forms.Label();
this.txtAmigoToken=newSystem.Windows.Forms.TextBox();
this.lblFilename=newSystem.Windows.Forms.Label();
this.txtFilename=newSystem.Windows.Forms.TextBox();
this.btnBrowse=newSystem.Windows.Forms.Button();
this.txtFileData=newSystem.Windows.Forms.TextBox();
this.lblFileData=newSystem.Windows.Forms.Label();
this.btnUpload=newSystem.Windows.Forms.Button();
this.openFileDialog1=newSystem.Windows.Forms.OpenFileDialog();
this.txtResponse=newSystem.Windows.Forms.TextBox();
this.SuspendLayout();
//
//lblAmigoToken
//
this.lblAmigoToken.Location=newSystem.Drawing.Point(40,48);
this.lblAmigoToken.Name="lblAmigoToken";
this.lblAmigoToken.Size=newSystem.Drawing.Size(72,23);
this.lblAmigoToken.TabIndex=0;
this.lblAmigoToken.Text="AmigoToken";
//
//txtAmigoToken
//
this.txtAmigoToken.Location=newSystem.Drawing.Point(120,48);
this.txtAmigoToken.Name="txtAmigoToken";
this.txtAmigoToken.Size=newSystem.Drawing.Size(248,21);
this.txtAmigoToken.TabIndex=1;
this.txtAmigoToken.Text="";
//
//lblFilename
//
this.lblFilename.Location=newSystem.Drawing.Point(40,96);
this.lblFilename.Name="lblFilename";
this.lblFilename.Size=newSystem.Drawing.Size(80,23);
this.lblFilename.TabIndex=2;
this.lblFilename.Text="Filename";
//
//txtFilename
//
this.txtFilename.Location=newSystem.Drawing.Point(120,96);
this.txtFilename.Name="txtFilename";
this.txtFilename.Size=newSystem.Drawing.Size(248,21);
this.txtFilename.TabIndex=3;
this.txtFilename.Text="";
//
//btnBrowse
//
this.btnBrowse.Location=newSystem.Drawing.Point(296,144);
this.btnBrowse.Name="btnBrowse";
this.btnBrowse.TabIndex=4;
this.btnBrowse.Text="浏览...";
this.btnBrowse.Click+=newSystem.EventHandler(this.btnBrowse_Click);
//
//txtFileData
//
this.txtFileData.Location=newSystem.Drawing.Point(120,144);
this.txtFileData.Name="txtFileData";
this.txtFileData.Size=newSystem.Drawing.Size(168,21);
this.txtFileData.TabIndex=5;
this.txtFileData.Text="";
//
//lblFileData
//
this.lblFileData.Location=newSystem.Drawing.Point(40,144);
this.lblFileData.Name="lblFileData";
this.lblFileData.Size=newSystem.Drawing.Size(72,23);
this.lblFileData.TabIndex=6;
this.lblFileData.Text="FileData";
//
//btnUpload
//
this.btnUpload.Location=newSystem.Drawing.Point(48,184);
this.btnUpload.Name="btnUpload";
this.btnUpload.TabIndex=7;
this.btnUpload.Text="Upload";
this.btnUpload.Click+=newSystem.EventHandler(this.btnUpload_Click);
//
//txtResponse
//
this.txtResponse.Location=newSystem.Drawing.Point(136,184);
this.txtResponse.Multiline=true;
this.txtResponse.Name="txtResponse";
this.txtResponse.Size=newSystem.Drawing.Size(248,72);
this.txtResponse.TabIndex=8;
this.txtResponse.Text="";
//
//frmUpload
//
this.AutoScaleBaseSize=newSystem.Drawing.Size(6,14);
this.ClientSize=newSystem.Drawing.Size(400,269);
this.Controls.Add(this.txtResponse);
this.Controls.Add(this.btnUpload);
this.Controls.Add(this.lblFileData);
this.Controls.Add(this.txtFileData);
this.Controls.Add(this.btnBrowse);
this.Controls.Add(this.txtFilename);
this.Controls.Add(this.lblFilename);
this.Controls.Add(this.txtAmigoToken);
this.Controls.Add(this.lblAmigoToken);
this.Name="frmUpload";
this.Text="frmUpload";
this.ResumeLayout(false);
}
#endregion
/**////<summary>
///应用程序的主入口点。
///</summary>
[STAThread]
staticvoidMain()
...{
Application.Run(newfrmUpload());
}
privatevoidbtnUpload_Click(objectsender,System.EventArgse)
...{
//非空检验
if(txtAmigoToken.Text.Trim()==""||txtFilename.Text==""||txtFileData.Text.Trim()=="")
...{
MessageBox.Show("Pleasefilldata");
return;
}
//所要上传的文件路径
stringpath=txtFileData.Text.Trim();
//检查文件是否存在
if(!File.Exists(path))
...{
MessageBox.Show("{0}doesnotexist!",path);
return;
}
//读文件流
FileStreamfs=newFileStream(path,FileMode.Open,
FileAccess.Read,FileShare.Read);
//这部分需要完善
stringContentType="application/octet-stream";
byte[]fileBytes=newbyte[fs.Length];
fs.Read(fileBytes,0,Convert.ToInt32(fs.Length));
//生成需要上传的二进制数组
CreateBytescb=newCreateBytes();
//所有表单数据
ArrayListbytesArray=newArrayList();
//普通表单
bytesArray.Add(cb.CreateFieldData("FileName",txtFilename.Text));
bytesArray.Add(cb.CreateFieldData("AmigoToken",txtAmigoToken.Text));
//文件表单
bytesArray.Add(cb.CreateFieldData("FileData",path
,ContentType,fileBytes));
//合成所有表单并生成二进制数组
byte[]bytes=cb.JoinBytes(bytesArray);
//返回的内容
byte[]responseBytes;
//上传到指定Url
booluploaded=cb.UploadData("http://localhost/UploadData/UploadAvatar.aspx",bytes,outresponseBytes);
//将返回的内容输出到文件
using(FileStreamfile=newFileStream(@"c:response.text",FileMode.Create,FileAccess.Write,FileShare.Read))
...{
file.Write(responseBytes,0,responseBytes.Length);
}
txtResponse.Text=System.Text.Encoding.UTF8.GetString(responseBytes);
}
privatevoidbtnBrowse_Click(objectsender,System.EventArgse)
...{
if(openFileDialog1.ShowDialog()==DialogResult.OK)
...{
txtFileData.Text=openFileDialog1.FileName;
}
}
}
}
完整的代码见附件:UploadData.rar(38K)(http://bbs.openlab.net.cn/PostAttachment.aspx?PostID=400927),解压后给web目录建个虚拟目录"UploadData",其中UploadAvatar.aspx是实际的上传处理页,如果上传成功,则返回文件名和文件类型等信息。default.aspx是asp.net页面来调用WebClient.UploadData方法提交数据,UploadDataWin项目则是winform程序调用。