博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Multipart forms from C# client
阅读量:6986 次
发布时间:2019-06-27

本文共 12421 字,大约阅读时间需要 41 分钟。

publicclassPostData{
privateList
m_Params;publicList
Params{
get {
return m_Params;}set{
m_Params = value;}}publicPostData(){
m_Params =newList
();// Add sample param m_Params.Add(newPostDataParam("email","MyEmail",PostDataParamType.Field));}///
/// Returns the parameters array formatted for multi-part/form data/// ///
publicstringGetPostData(){
// Get boundary, default is --AaB03xstring boundary =ConfigurationManager.AppSettings["ContentBoundary"].ToString();StringBuilder sb =newStringBuilder();foreach(PostDataParam p in m_Params){
sb.AppendLine(boundary);if(p.Type==PostDataParamType.File){
sb.AppendLine(string.Format("Content-Disposition: file; name=\"{0}\"; filename=\"{1}\"", p.Name, p.FileName)); sb.AppendLine("Content-Type: text/plain"); sb.AppendLine(); sb.AppendLine(p.Value);}else{
sb.AppendLine(string.Format("Content-Disposition: form-data; name=\"{0}\"", p.Name)); sb.AppendLine(); sb.AppendLine(p.Value);}} sb.AppendLine(boundary);return sb.ToString();}}publicenumPostDataParamType{
Field,File}publicclassPostDataParam{
publicPostDataParam(string name,string value,PostDataParamType type){
Name= name;Value= value;Type= type;}publicstringName;publicstringFileName;publicstringValue;publicPostDataParamTypeType;}

To send the data you then need to:

 
HttpWebRequest oRequest =null;oRequest =(HttpWebRequest)HttpWebRequest.Create(oURL.URL);oRequest.ContentType="multipart/form-data";   					oRequest.Method="POST";PostData pData =newPostData();byte[] buffer = encoding.GetBytes(pData.GetPostData());// Set content length of our dataoRequest.ContentLength= buffer.Length;// Dump our buffered postdata to the stream, booyahoStream = oRequest.GetRequestStream();oStream.Write(buffer,0, buffer.Length);oStream.Close();// get the responseoResponse =(HttpWebResponse)oRequest.GetResponse();
Here is the FormUpload class:
// Implements multipart/form-data POST in C# http://www.ietf.org/rfc/rfc2388.txt// http://www.briangrinstead.com/blog/multipart-form-post-in-cpublicstaticclassFormUpload{
privatestaticreadonlyEncoding encoding =Encoding.UTF8;publicstaticHttpWebResponseMultipartFormDataPost(string postUrl,string userAgent,Dictionary
postParameters){
string formDataBoundary =String.Format("----------{0:N}",Guid.NewGuid());string contentType ="multipart/form-data; boundary="+ formDataBoundary;byte[] formData =GetMultipartFormData(postParameters, formDataBoundary);returnPostForm(postUrl, userAgent, contentType, formData);}privatestaticHttpWebResponsePostForm(string postUrl,string userAgent,string contentType,byte[] formData){
HttpWebRequest request =WebRequest.Create(postUrl)asHttpWebRequest;if(request ==null){
thrownewNullReferenceException("request is not a http request");}// Set up the request properties. request.Method="POST"; request.ContentType= contentType; request.UserAgent= userAgent; request.CookieContainer=newCookieContainer(); request.ContentLength= formData.Length;// You could add authentication here as well if needed:// request.PreAuthenticate = true;// request.AuthenticationLevel = System.Net.Security.AuthenticationLevel.MutualAuthRequested;// request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.Encoding.Default.GetBytes("username" + ":" + "password")));// Send the form data to the request. using (Stream requestStream = request.GetRequestStream()){
requestStream.Write(formData,0, formData.Length); requestStream.Close();}return request.GetResponse()asHttpWebResponse;}privatestaticbyte[]GetMultipartFormData(Dictionary
postParameters,string boundary){
Stream formDataStream =newSystem.IO.MemoryStream(); bool needsCLRF =false;foreach(var param in postParameters){
// Thanks to feedback from commenters, add a CRLF to allow multiple parameters to be added.// Skip it on the first parameter, add it to subsequent parameters.if(needsCLRF) formDataStream.Write(encoding.GetBytes("\r\n"),0, encoding.GetByteCount("\r\n")); needsCLRF =true;if(param.ValueisFileParameter){
FileParameter fileToUpload =(FileParameter)param.Value;// Add just the first part of this param, since we will write the file data directly to the Streamstring header =string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n", boundary, param.Key, fileToUpload.FileName?? param.Key, fileToUpload.ContentType??"application/octet-stream"); formDataStream.Write(encoding.GetBytes(header),0, encoding.GetByteCount(header));// Write the file data directly to the Stream, rather than serializing it to a string. formDataStream.Write(fileToUpload.File,0, fileToUpload.File.Length);}else{
string postData =string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}", boundary, param.Key, param.Value); formDataStream.Write(encoding.GetBytes(postData),0, encoding.GetByteCount(postData));}}// Add the end of the request. Start with a newlinestring footer ="\r\n--"+ boundary +"--\r\n"; formDataStream.Write(encoding.GetBytes(footer),0, encoding.GetByteCount(footer));// Dump the Stream into a byte[] formDataStream.Position=0;byte[] formData =newbyte[formDataStream.Length]; formDataStream.Read(formData,0, formData.Length); formDataStream.Close();return formData;}publicclassFileParameter{
publicbyte[]File{
get;set;}publicstringFileName{
get;set;}publicstringContentType{
get;set;}publicFileParameter(byte[] file):this(file,null){
}publicFileParameter(byte[] file,string filename):this(file, filename,null){
}publicFileParameter(byte[] file,string filename,string contenttype){
File= file;FileName= filename;ContentType= contenttype;}}}
 

Here is the calling code, which uploads a file and a few normal post parameters:

 
// Read file dataFileStream fs =newFileStream("c:\\people.doc",FileMode.Open,FileAccess.Read);byte[] data =newbyte[fs.Length];fs.Read(data,0, data.Length);fs.Close();// Generate post objectsDictionary
postParameters =newDictionary
();postParameters.Add("filename","People.doc");postParameters.Add("fileformat","doc");postParameters.Add("file",newFormUpload.FileParameter(data,"People.doc","application/msword"));// Create request and receive responsestring postURL ="http://localhost";string userAgent ="Someone";HttpWebResponse webResponse =FormUpload.MultipartFormDataPost(postURL, userAgent, postParameters);// Process responseStreamReader responseReader =newStreamReader(webResponse.GetResponseStream());string fullResponse = responseReader.ReadToEnd();webResponse.Close();Response.Write(fullResponse);
 

Building on dnolans example, this is the version I could actually get to work (there were some errors with the boundary, encoding wasn't set) :-)

 

To send the data:

 
HttpWebRequest oRequest =null;oRequest =(HttpWebRequest)HttpWebRequest.Create("http://you.url.here");oRequest.ContentType="multipart/form-data; boundary="+PostData.boundary;oRequest.Method="POST";PostData pData =newPostData();Encoding encoding =Encoding.UTF8;Stream oStream =null;/* ... set the parameters, read files, etc. IE:   pData.Params.Add(new PostDataParam("email", "example@example.com", PostDataParamType.Field));   pData.Params.Add(new PostDataParam("fileupload", "filename.txt", "filecontents" PostDataParamType.File));*/byte[] buffer = encoding.GetBytes(pData.GetPostData());oRequest.ContentLength= buffer.Length;oStream = oRequest.GetRequestStream();oStream.Write(buffer,0, buffer.Length);oStream.Close();HttpWebResponse oResponse =(HttpWebResponse)oRequest.GetResponse();
 

The PostData class should look like:

 
publicclassPostData{
// Change this if you need to, not necessarypublicstaticstring boundary ="AaB03x";privateList
m_Params;publicList
Params{
get {
return m_Params;}set{
m_Params = value;}}publicPostData(){
m_Params =newList
();}///
/// Returns the parameters array formatted for multi-part/form data/// ///
publicstringGetPostData(){
StringBuilder sb =newStringBuilder();foreach(PostDataParam p in m_Params){
sb.AppendLine("--"+ boundary);if(p.Type==PostDataParamType.File){
sb.AppendLine(string.Format("Content-Disposition: file; name=\"{0}\"; filename=\"{1}\"", p.Name, p.FileName)); sb.AppendLine("Content-Type: application/octet-stream"); sb.AppendLine(); sb.AppendLine(p.Value);}else{
sb.AppendLine(string.Format("Content-Disposition: form-data; name=\"{0}\"", p.Name)); sb.AppendLine(); sb.AppendLine(p.Value);}} sb.AppendLine("--"+ boundary +"--");return sb.ToString();}}publicenumPostDataParamType{
Field,File}publicclassPostDataParam{
publicPostDataParam(string name,string value,PostDataParamType type){
Name= name;Value= value;Type= type;}publicPostDataParam(string name,string filename,string value,PostDataParamType type){
Name= name;Value= value;FileName= filename;Type= type;}publicstringName;publicstringFileName;publicstringValue;publicPostDataParamTypeType;}
 
namespace WindowsFormsApplication1{
publicstaticclassFormUpload{
privatestaticstringNewDataBoundary(){
Random rnd =newRandom();string formDataBoundary ="";while(formDataBoundary.Length<15){
formDataBoundary = formDataBoundary + rnd.Next();} formDataBoundary = formDataBoundary.Substring(0,15); formDataBoundary ="-----------------------------"+ formDataBoundary;return formDataBoundary;}publicstaticHttpWebResponseMultipartFormDataPost(string postUrl,IEnumerable
cookies,Dictionary
postParameters){
string boundary =NewDataBoundary();HttpWebRequest request =(HttpWebRequest)WebRequest.Create(postUrl);// Set up the request properties request.Method="POST"; request.ContentType="multipart/form-data; boundary="+ boundary; request.UserAgent="PhasDocAgent 1.0"; request.CookieContainer=newCookieContainer();foreach(var cookie in cookies){
request.CookieContainer.Add(cookie);}#region WRITING STREAM using (Stream formDataStream = request.GetRequestStream()){
foreach(var param in postParameters){
if(param.Value.StartsWith("file://")){
string filepath = param.Value.Substring(7);// Add just the first part of this param, since we will write the file data directly to the Streamstring header =string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"; filename=\"{2}\";\r\nContent-Type: {3}\r\n\r\n", boundary, param.Key,Path.GetFileName(filepath)?? param.Key,MimeTypes.GetMime(filepath)); formDataStream.Write(Encoding.UTF8.GetBytes(header),0, header.Length);// Write the file data directly to the Stream, rather than serializing it to a string.byte[] buffer =newbyte[2048];FileStream fs =newFileStream(filepath,FileMode.Open);for(int i =0; i < fs.Length;){
int k = fs.Read(buffer,0, buffer.Length);if(k >0){
formDataStream.Write(buffer,0, k);} i = i + k;} fs.Close();}else{
string postData =string.Format("--{0}\r\nContent-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n", boundary, param.Key, param.Value); formDataStream.Write(Encoding.UTF8.GetBytes(postData),0, postData.Length);}}// Add the end of the requestbyte[] footer =Encoding.UTF8.GetBytes("\r\n--"+ boundary +"--\r\n"); formDataStream.Write(footer,0, footer.Length); request.ContentLength= formDataStream.Length; formDataStream.Close();}#endregionreturn request.GetResponse()asHttpWebResponse;}}}
 

参考

转载于:https://www.cnblogs.com/zcm123/archive/2013/04/24/3040584.html

你可能感兴趣的文章
django的用户认证管理,如何使用session(1)
查看>>
DataTableHelper
查看>>
实例说明optimize table在优化mysql时很重要
查看>>
shell惊鸿
查看>>
三个快速且简单的让你的大脑安静下来的方法
查看>>
UWP入门(十二)--数据绑定用法
查看>>
aspx代码审计-1
查看>>
快速php日志,写内容到文件,把日志写到log文件
查看>>
linux percpu机制解析【转】
查看>>
C#多线程编程
查看>>
Nutch配置:nutch-default.xml详解
查看>>
EF6 在原有数据库中使用 CodeFirst 总复习(一、搭建基础环境)
查看>>
[svc]tomcat配置文件详解-最简单的基于mvn的war包
查看>>
centos--git搭建之Gogs安装
查看>>
Hive:有表A与表B进行inner join,如果A分组内包含有数据,使用A,否则使用B分组下的数据...
查看>>
maven下的jar项目打包的方法
查看>>
为确保固定资产的财务帐与实物帐一致,应采取的措施
查看>>
带你从零学ReactNative开发跨平台App开发-[react native 仿boss直聘](十三)
查看>>
c#的托管代码和非托管代码的理解
查看>>
ReactNative之Flux框架的使用
查看>>