您的位置:首页 > 理论基础 > 计算机网络

使用WebClient或HttpWebRequest模拟上传文件和数据

2007-06-20 15:13 841 查看
假如某网站有个表单,例如(url: http://localhost/login.aspx):

帐号


密码




我们需要在程序中提交数据到这个表单,对于这种表单,我们可以使用 WebClient.UploadData 方法来实现,将所要上传的数据拼成字符即可,程序很简单:




string uriString = "http://localhost/login.aspx";


// 创建一个新的 WebClient 实例.


WebClient myWebClient = new WebClient();


string postData = "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):

文件




对于这种表单,我们可以使用


String uriString = "http://localhost/uploadFile.aspx";




// 创建一个新的 WebClient 实例.


WebClient myWebClient = new WebClient();




string fileName = @"C:/upload.txt";




// 直接上传,并获取返回的二进制数据.


byte[] responseArray = myWebClient.UploadFile(uriString,"POST",fileName);






还有一种表单,不仅有文字,还有文件,例如(url: http://localhost/uploadData.aspx):

文件名


文件




对于这种表单,似乎前面的两种方法都不能适用,对于第一种方法,不能直接拼字符串,对于第二种,我们只能传文件,重新回到第一个方法,注意参数:


public byte[] UploadData(


string address,


string method,


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"


default filename


-----------------------------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 方法上载文件数据了。




具体代码如下:


生成二进制数据类的封装




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


}


}






在Winform中调用






using System;


using System.Drawing;


using System.Collections;


using System.ComponentModel;


using System.Windows.Forms;


using System.Data;




using UploadData.Common;


using System.IO;




namespace UploadDataWin








{




/**//**//**//// <summary>


/// frmUpload 的摘要说明。


/// </summary>


public class frmUpload : System.Windows.Forms.Form








{


private System.Windows.Forms.Label lblAmigoToken;


private System.Windows.Forms.TextBox txtAmigoToken;


private System.Windows.Forms.Label lblFilename;


private System.Windows.Forms.TextBox txtFilename;


private System.Windows.Forms.Button btnBrowse;


private System.Windows.Forms.TextBox txtFileData;


private System.Windows.Forms.Label lblFileData;


private System.Windows.Forms.Button btnUpload;


private System.Windows.Forms.OpenFileDialog openFileDialog1;


private System.Windows.Forms.TextBox txtResponse;




/**//**//**//// <summary>


/// 必需的设计器变量。


/// </summary>


private System.ComponentModel.Container components = null;




public frmUpload()








{


//


// Windows 窗体设计器支持所必需的


//


InitializeComponent();




//


// TODO: 在 InitializeComponent 调用后添加任何构造函数代码


//


}






/**//**//**//// <summary>


/// 清理所有正在使用的资源。


/// </summary>


protected override void Dispose( bool disposing )








{


if( disposing )








{


if (components != null)








{


components.Dispose();


}


}


base.Dispose( disposing );


}






Windows 窗体设计器生成的代码Windows 窗体设计器生成的代码#region Windows 窗体设计器生成的代码




/**//**//**//// <summary>


/// 设计器支持所需的方法 - 不要使用代码编辑器修改


/// 此方法的内容。


/// </summary>


private void InitializeComponent()








{


this.lblAmigoToken = new System.Windows.Forms.Label();


this.txtAmigoToken = new System.Windows.Forms.TextBox();


this.lblFilename = new System.Windows.Forms.Label();


this.txtFilename = new System.Windows.Forms.TextBox();


this.btnBrowse = new System.Windows.Forms.Button();


this.txtFileData = new System.Windows.Forms.TextBox();


this.lblFileData = new System.Windows.Forms.Label();


this.btnUpload = new System.Windows.Forms.Button();


this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();


this.txtResponse = new System.Windows.Forms.TextBox();


this.SuspendLayout();


//


// lblAmigoToken


//


this.lblAmigoToken.Location = new System.Drawing.Point(40, 48);


this.lblAmigoToken.Name = "lblAmigoToken";


this.lblAmigoToken.Size = new System.Drawing.Size(72, 23);


this.lblAmigoToken.TabIndex = 0;


this.lblAmigoToken.Text = "AmigoToken";


//


// txtAmigoToken


//


this.txtAmigoToken.Location = new System.Drawing.Point(120, 48);


this.txtAmigoToken.Name = "txtAmigoToken";


this.txtAmigoToken.Size = new System.Drawing.Size(248, 21);


this.txtAmigoToken.TabIndex = 1;


this.txtAmigoToken.Text = "";


//


// lblFilename


//


this.lblFilename.Location = new System.Drawing.Point(40, 96);


this.lblFilename.Name = "lblFilename";


this.lblFilename.Size = new System.Drawing.Size(80, 23);


this.lblFilename.TabIndex = 2;


this.lblFilename.Text = "Filename";


//


// txtFilename


//


this.txtFilename.Location = new System.Drawing.Point(120, 96);


this.txtFilename.Name = "txtFilename";


this.txtFilename.Size = new System.Drawing.Size(248, 21);


this.txtFilename.TabIndex = 3;


this.txtFilename.Text = "";


//


// btnBrowse


//


this.btnBrowse.Location = new System.Drawing.Point(296, 144);


this.btnBrowse.Name = "btnBrowse";


this.btnBrowse.TabIndex = 4;


this.btnBrowse.Text = "浏览

";


this.btnBrowse.Click += new System.EventHandler(this.btnBrowse_Click);


//


// txtFileData


//


this.txtFileData.Location = new System.Drawing.Point(120, 144);


this.txtFileData.Name = "txtFileData";


this.txtFileData.Size = new System.Drawing.Size(168, 21);


this.txtFileData.TabIndex = 5;


this.txtFileData.Text = "";


//


// lblFileData


//


this.lblFileData.Location = new System.Drawing.Point(40, 144);


this.lblFileData.Name = "lblFileData";


this.lblFileData.Size = new System.Drawing.Size(72, 23);


this.lblFileData.TabIndex = 6;


this.lblFileData.Text = "FileData";


//


// btnUpload


//


this.btnUpload.Location = new System.Drawing.Point(48, 184);


this.btnUpload.Name = "btnUpload";


this.btnUpload.TabIndex = 7;


this.btnUpload.Text = "Upload";


this.btnUpload.Click += new System.EventHandler(this.btnUpload_Click);


//


// txtResponse


//


this.txtResponse.Location = new System.Drawing.Point(136, 184);


this.txtResponse.Multiline = true;


this.txtResponse.Name = "txtResponse";


this.txtResponse.Size = new System.Drawing.Size(248, 72);


this.txtResponse.TabIndex = 8;


this.txtResponse.Text = "";


//


// frmUpload


//


this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);


this.ClientSize = new System.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]


static void Main()








{


Application.Run(new frmUpload());


}




private void btnUpload_Click(object sender, System.EventArgs e)








{


// 非空检验


if (txtAmigoToken.Text.Trim() == "" || txtFilename.Text == "" || txtFileData.Text.Trim() == "")








{


MessageBox.Show("Please fill data");


return;


}




// 所要上传的文件路径


string path = txtFileData.Text.Trim();




// 检查文件是否存在


if (!File.Exists(path))








{


MessageBox.Show("{0} does not exist!", path);


return;


}




// 读文件流


FileStream fs = new FileStream(path, FileMode.Open,


FileAccess.Read, FileShare.Read);





// 这部分需要完善


string ContentType = "application/octet-stream";


byte[] fileBytes = new byte[fs.Length];


fs.Read(fileBytes, 0, Convert.ToInt32(fs.Length));






// 生成需要上传的二进制数组


CreateBytes cb = new CreateBytes();


// 所有表单数据


ArrayList bytesArray = new ArrayList();


// 普通表单


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


bool uploaded = cb.UploadData("http://localhost/UploadData/UploadAvatar.aspx", bytes, out responseBytes);




// 将返回的内容输出到文件


using (FileStream file = new FileStream(@"c:/response.text", FileMode.Create, FileAccess.Write, FileShare.Read))








{


file.Write(responseBytes, 0, responseBytes.Length);


}




txtResponse.Text = System.Text.Encoding.UTF8.GetString(responseBytes);




}




private void btnBrowse_Click(object sender, System.EventArgs e)








{


if(openFileDialog1.ShowDialog() == DialogResult.OK)








{


txtFileData.Text = openFileDialog1.FileName;


}




}


}


}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: