一个 http 请求类 ,支持文件上传,从淘宝 top sdk 里面扣出来的,蛮好用的,做个记录而已。

调用代码:

       Dictionary<string, string> textParas = new Dictionary<string, string>();
textParas.Add("username", "jersey");
textParas.Add("password", "000000"); Dictionary<string, FileItem> fileParas = new Dictionary<string, FileItem>();
fileParas.Add("file1", new FileItem("E:\\123.jpg"));
fileParas.Add("file2", new FileItem("E:\\123.jpg")); WebUtils webUtils=new WebUtils();
webUtils.Timeout=50000;
webUtils.DoPost("http://www.baidu.com/api/index.php",textParas,fileParas,null);

  

类代码:

using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Web; namespace tools
{
/// <summary>
/// 网络工具类。
/// </summary>
public sealed class WebUtils
{
private int _timeout = 20000;
private int _readWriteTimeout = 60000;
private bool _ignoreSSLCheck = true;
private bool _disableWebProxy = false; /// <summary>
/// 等待请求开始返回的超时时间
/// </summary>
public int Timeout
{
get { return this._timeout; }
set { this._timeout = value; }
} /// <summary>
/// 等待读取数据完成的超时时间
/// </summary>
public int ReadWriteTimeout
{
get { return this._readWriteTimeout; }
set { this._readWriteTimeout = value; }
} /// <summary>
/// 是否忽略SSL检查
/// </summary>
public bool IgnoreSSLCheck
{
get { return this._ignoreSSLCheck; }
set { this._ignoreSSLCheck = value; }
} /// <summary>
/// 是否禁用本地代理
/// </summary>
public bool DisableWebProxy
{
get { return this._disableWebProxy; }
set { this._disableWebProxy = value; }
} /// <summary>
/// 执行HTTP POST请求。
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="textParams">请求文本参数</param>
/// <returns>HTTP响应</returns>
public string DoPost(string url, IDictionary<string, string> textParams)
{
return DoPost(url, textParams, null);
} /// <summary>
/// 执行HTTP POST请求。
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="textParams">请求文本参数</param>
/// <param name="headerParams">请求头部参数</param>
/// <returns>HTTP响应</returns>
public string DoPost(string url, IDictionary<string, string> textParams, IDictionary<string, string> headerParams)
{
HttpWebRequest req = GetWebRequest(url, "POST", headerParams);
req.ContentType = "application/x-www-form-urlencoded;charset=utf-8"; byte[] postData = Encoding.UTF8.GetBytes(BuildQuery(textParams));
System.IO.Stream reqStream = req.GetRequestStream();
reqStream.Write(postData, 0, postData.Length);
reqStream.Close(); HttpWebResponse rsp = (HttpWebResponse)req.GetResponse();
Encoding encoding = GetResponseEncoding(rsp);
return GetResponseAsString(rsp, encoding);
} /// <summary>
/// 执行HTTP GET请求。
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="textParams">请求文本参数</param>
/// <returns>HTTP响应</returns>
public string DoGet(string url, IDictionary<string, string> textParams)
{
return DoGet(url, textParams, null);
} /// <summary>
/// 执行HTTP GET请求。
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="textParams">请求文本参数</param>
/// <param name="headerParams">请求头部参数</param>
/// <returns>HTTP响应</returns>
public string DoGet(string url, IDictionary<string, string> textParams, IDictionary<string, string> headerParams)
{
if (textParams != null && textParams.Count > 0)
{
url = BuildRequestUrl(url, textParams);
} HttpWebRequest req = GetWebRequest(url, "GET", headerParams);
req.ContentType = "application/x-www-form-urlencoded;charset=utf-8"; HttpWebResponse rsp = (HttpWebResponse)req.GetResponse();
Encoding encoding = GetResponseEncoding(rsp);
return GetResponseAsString(rsp, encoding);
} /// <summary>
/// 执行带文件上传的HTTP POST请求。
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="textParams">请求文本参数</param>
/// <param name="fileParams">请求文件参数</param>
/// <param name="headerParams">请求头部参数</param>
/// <returns>HTTP响应</returns>
public string DoPost(string url, IDictionary<string, string> textParams, IDictionary<string, FileItem> fileParams, IDictionary<string, string> headerParams)
{
// 如果没有文件参数,则走普通POST请求
if (fileParams == null || fileParams.Count == 0)
{
return DoPost(url, textParams, headerParams);
} string boundary = DateTime.Now.Ticks.ToString("X"); // 随机分隔线 HttpWebRequest req = GetWebRequest(url, "POST", headerParams);
req.ContentType = "multipart/form-data;charset=utf-8;boundary=" + boundary; System.IO.Stream reqStream = req.GetRequestStream();
byte[] itemBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");
byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n"); // 组装文本请求参数
string textTemplate = "Content-Disposition:form-data;name=\"{0}\"\r\nContent-Type:text/plain\r\n\r\n{1}";
foreach (KeyValuePair<string, string> kv in textParams)
{
string textEntry = string.Format(textTemplate, kv.Key, kv.Value);
byte[] itemBytes = Encoding.UTF8.GetBytes(textEntry);
reqStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length);
reqStream.Write(itemBytes, 0, itemBytes.Length);
} // 组装文件请求参数
string fileTemplate = "Content-Disposition:form-data;name=\"{0}\";filename=\"{1}\"\r\nContent-Type:{2}\r\n\r\n";
foreach (KeyValuePair<string, FileItem> kv in fileParams)
{
string key = kv.Key;
FileItem fileItem = kv.Value;
if (!fileItem.IsValid())
{
throw new ArgumentException("FileItem is invalid");
}
string fileEntry = string.Format(fileTemplate, key, fileItem.GetFileName(), fileItem.GetMimeType());
byte[] itemBytes = Encoding.UTF8.GetBytes(fileEntry);
reqStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length);
reqStream.Write(itemBytes, 0, itemBytes.Length);
fileItem.Write(reqStream);
} reqStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
reqStream.Close(); HttpWebResponse rsp = (HttpWebResponse)req.GetResponse();
Encoding encoding = GetResponseEncoding(rsp);
return GetResponseAsString(rsp, encoding);
} /// <summary>
/// 执行带body体的POST请求。
/// </summary>
/// <param name="url">请求地址,含URL参数</param>
/// <param name="body">请求body体字节流</param>
/// <param name="contentType">body内容类型</param>
/// <param name="headerParams">请求头部参数</param>
/// <returns>HTTP响应</returns>
public string DoPost(string url, byte[] body, string contentType, IDictionary<string, string> headerParams)
{
HttpWebRequest req = GetWebRequest(url, "POST", headerParams);
req.ContentType = contentType;
if (body != null)
{
System.IO.Stream reqStream = req.GetRequestStream();
reqStream.Write(body, 0, body.Length);
reqStream.Close();
}
HttpWebResponse rsp = (HttpWebResponse)req.GetResponse();
Encoding encoding = GetResponseEncoding(rsp);
return GetResponseAsString(rsp, encoding);
} public HttpWebRequest GetWebRequest(string url, string method, IDictionary<string, string> headerParams)
{
HttpWebRequest req = null;
if (url.StartsWith("https", StringComparison.OrdinalIgnoreCase))
{
if (this._ignoreSSLCheck)
{
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(TrustAllValidationCallback);
}
req = (HttpWebRequest)WebRequest.CreateDefault(new Uri(url));
}
else
{
req = (HttpWebRequest)WebRequest.Create(url);
} if (this._disableWebProxy)
{
req.Proxy = null;
} if (headerParams != null && headerParams.Count > 0)
{
foreach (string key in headerParams.Keys)
{
req.Headers.Add(key, headerParams[key]);
}
} req.ServicePoint.Expect100Continue = false;
req.Method = method;
req.KeepAlive = true;
req.UserAgent = "top-sdk-net";
req.Accept = "text/xml,text/javascript";
req.Timeout = this._timeout;
req.ReadWriteTimeout = this._readWriteTimeout; return req;
} /// <summary>
/// 把响应流转换为文本。
/// </summary>
/// <param name="rsp">响应流对象</param>
/// <param name="encoding">编码方式</param>
/// <returns>响应文本</returns>
public string GetResponseAsString(HttpWebResponse rsp, Encoding encoding)
{
Stream stream = null;
StreamReader reader = null; try
{
// 以字符流的方式读取HTTP响应
stream = rsp.GetResponseStream();
if (Constants.CONTENT_ENCODING_GZIP.Equals(rsp.ContentEncoding, StringComparison.OrdinalIgnoreCase))
{
stream = new GZipStream(stream, CompressionMode.Decompress);
}
reader = new StreamReader(stream, encoding);
return reader.ReadToEnd();
}
finally
{
// 释放资源
if (reader != null) reader.Close();
if (stream != null) stream.Close();
if (rsp != null) rsp.Close();
}
} /// <summary>
/// 组装含参数的请求URL。
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="parameters">请求参数映射</param>
/// <returns>带参数的请求URL</returns>
public static string BuildRequestUrl(string url, IDictionary<string, string> parameters)
{
if (parameters != null && parameters.Count > 0)
{
return BuildRequestUrl(url, BuildQuery(parameters));
}
return url;
} /// <summary>
/// 组装含参数的请求URL。
/// </summary>
/// <param name="url">请求地址</param>
/// <param name="queries">一个或多个经过URL编码后的请求参数串</param>
/// <returns>带参数的请求URL</returns>
public static string BuildRequestUrl(string url, params string[] queries)
{
if (queries == null || queries.Length == 0)
{
return url;
} StringBuilder newUrl = new StringBuilder(url);
bool hasQuery = url.Contains("?");
bool hasPrepend = url.EndsWith("?") || url.EndsWith("&"); foreach (string query in queries)
{
if (!string.IsNullOrEmpty(query))
{
if (!hasPrepend)
{
if (hasQuery)
{
newUrl.Append("&");
}
else
{
newUrl.Append("?");
hasQuery = true;
}
}
newUrl.Append(query);
hasPrepend = false;
}
}
return newUrl.ToString();
} /// <summary>
/// 组装普通文本请求参数。
/// </summary>
/// <param name="parameters">Key-Value形式请求参数字典</param>
/// <returns>URL编码后的请求数据</returns>
public static string BuildQuery(IDictionary<string, string> parameters)
{
if (parameters == null || parameters.Count == 0)
{
return null;
} StringBuilder query = new StringBuilder();
bool hasParam = false; foreach (KeyValuePair<string, string> kv in parameters)
{
string name = kv.Key;
string value = kv.Value;
// 忽略参数名或参数值为空的参数
if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(value))
{
if (hasParam)
{
query.Append("&");
} query.Append(name);
query.Append("=");
query.Append(HttpUtility.UrlEncode(value, Encoding.UTF8));
hasParam = true;
}
} return query.ToString();
} private Encoding GetResponseEncoding(HttpWebResponse rsp)
{
string charset = rsp.CharacterSet;
if (string.IsNullOrEmpty(charset))
{
charset = Constants.CHARSET_UTF8;
}
return Encoding.GetEncoding(charset);
} private static bool TrustAllValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
return true; // 忽略SSL证书检查
}
} public class Constants
{
public const string CONTENT_ENCODING_GZIP = "gzip";
public const string CHARSET_UTF8 = "utf-8";
public const string CTYPE_DEFAULT = "application/octet-stream";
public const int READ_BUFFER_SIZE = 1024 * 4;
} /// <summary>
/// 文件元数据。
/// 可以使用以下几种构造方法:
/// 本地路径:new FileItem("C:/temp.jpg");
/// 本地文件:new FileItem(new FileInfo("C:/temp.jpg"));
/// 字节数组:new FileItem("abc.jpg", bytes);
/// 输入流:new FileItem("abc.jpg", stream);
/// </summary>
public class FileItem
{
private Contract contract; /// <summary>
/// 基于本地文件的构造器。
/// </summary>
/// <param name="fileInfo">本地文件</param>
public FileItem(FileInfo fileInfo)
{
this.contract = new LocalContract(fileInfo);
} /// <summary>
/// 基于本地文件全路径的构造器。
/// </summary>
/// <param name="filePath">本地文件全路径</param>
public FileItem(string filePath)
: this(new FileInfo(filePath))
{
} /// <summary>
/// 基于文件名和字节数组的构造器。
/// </summary>
/// <param name="fileName">文件名称(服务端持久化字节数组到磁盘时的文件名)</param>
/// <param name="content">文件字节数组</param>
public FileItem(string fileName, byte[] content)
: this(fileName, content, null)
{
} /// <summary>
/// 基于文件名、字节数组和媒体类型的构造器。
/// </summary>
/// <param name="fileName">文件名(服务端持久化字节数组到磁盘时的文件名)</param>
/// <param name="content">文件字字节数组</param>
/// <param name="mimeType">媒体类型</param>
public FileItem(string fileName, byte[] content, string mimeType)
{
this.contract = new ByteArrayContract(fileName, content, mimeType);
} /// <summary>
/// 基于文件名和输入流的构造器。
/// </summary>
/// <param name="fileName">文件名称(服务端持久化输入流到磁盘时的文件名)</param>
/// <param name="content">文件输入流</param>
public FileItem(string fileName, Stream stream)
: this(fileName, stream, null)
{
} /// <summary>
/// 基于文件名、输入流和媒体类型的构造器。
/// </summary>
/// <param name="fileName">文件名(服务端持久化输入流到磁盘时的文件名)</param>
/// <param name="content">文件输入流</param>
/// <param name="mimeType">媒体类型</param>
public FileItem(string fileName, Stream stream, string mimeType)
{
this.contract = new StreamContract(fileName, stream, mimeType);
} public bool IsValid()
{
return this.contract.IsValid();
} public long GetFileLength()
{
return this.contract.GetFileLength();
} public string GetFileName()
{
return this.contract.GetFileName();
} public string GetMimeType()
{
return this.contract.GetMimeType();
} public void Write(Stream output)
{
this.contract.Write(output);
}
} internal interface Contract
{
bool IsValid();
string GetFileName();
string GetMimeType();
long GetFileLength();
void Write(Stream output);
} internal class LocalContract : Contract
{
private FileInfo fileInfo; public LocalContract(FileInfo fileInfo)
{
this.fileInfo = fileInfo;
} public long GetFileLength()
{
return this.fileInfo.Length;
} public string GetFileName()
{
return this.fileInfo.Name;
} public string GetMimeType()
{
return Constants.CTYPE_DEFAULT;
} public bool IsValid()
{
return this.fileInfo != null && this.fileInfo.Exists;
} public void Write(Stream output)
{
using (BufferedStream bfs = new BufferedStream(this.fileInfo.OpenRead()))
{
int n = 0;
byte[] buffer = new byte[Constants.READ_BUFFER_SIZE];
while ((n = bfs.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, n);
}
}
}
} internal class ByteArrayContract : Contract
{
private string fileName;
private byte[] content;
private string mimeType; public ByteArrayContract(string fileName, byte[] content, string mimeType)
{
this.fileName = fileName;
this.content = content;
this.mimeType = mimeType;
} public bool IsValid()
{
return this.content != null && this.fileName != null;
} public long GetFileLength()
{
return this.content.Length;
} public string GetFileName()
{
return this.fileName;
} public string GetMimeType()
{
if (string.IsNullOrEmpty(this.mimeType))
{
return Constants.CTYPE_DEFAULT;
}
else
{
return this.mimeType;
}
} public void Write(Stream output)
{
output.Write(this.content, 0, this.content.Length);
}
} internal class StreamContract : Contract
{
private string fileName;
private Stream stream;
private string mimeType; public StreamContract(string fileName, Stream stream, string mimeType)
{
this.fileName = fileName;
this.stream = stream;
this.mimeType = mimeType;
} public long GetFileLength()
{
return 0L;
} public string GetFileName()
{
return this.fileName;
} public string GetMimeType()
{
if (string.IsNullOrEmpty(mimeType))
{
return Constants.CTYPE_DEFAULT;
}
else
{
return this.mimeType;
}
} public bool IsValid()
{
return this.stream != null && this.fileName != null;
} public void Write(Stream output)
{
using (this.stream)
{
int n = 0;
byte[] buffer = new byte[Constants.READ_BUFFER_SIZE];
while ((n = this.stream.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, n);
}
}
}
}
}

  

一个比较强大的HTTP请求类,支持文本参数和文件参数。的更多相关文章

  1. C# 一个特别不错的http请求类

    using System; using System.Collections; using System.Collections.Generic; using System.Collections.S ...

  2. Afreechart很强大的图表库,支持股票曲线图,饼图,曲线

    Afreechart是一个很强大的图表库,支持股票曲线图,饼图,曲线等.源码下载:http://www.23code.com/afreechart/

  3. 一个linux下简单的纯C++实现Http请求类(GET,POST,上传,下载)

    目录 一个linux下简单的纯C++实现Http请求类(GET,POST,上传,下载) Http协议简述 HttpRequest类设计 请求部分 接收部分 关于上传和下载 Cpp实现 关于源码中的Lo ...

  4. 基于Volley,Gson封装支持JWT无状态安全验证和数据防篡改的GsonRequest网络请求类

    这段时间做新的Android项目的client和和REST API通讯框架架构设计.使用了非常多新技术,终于的方案也相当简洁优雅.client仅仅须要传Java对象,server端返回json字符串, ...

  5. 一个高性能的对象属性复制类,支持不同类型对象间复制,支持Nullable<T>类型属性

    由于在实际应用中,需要对大量的对象属性进行复制,原来的方法是通过反射实现,在量大了以后,反射的性能问题就凸显出来了,必须用Emit来实现. 搜了一圈代码,没发现适合的,要么只能在相同类型对象间复制,要 ...

  6. block传值以及利用block封装一个网络请求类

    1.block在俩个UIViewController间传值 近期刚学了几招block 的高级使用方法,事实上就是利用block语法在俩个UIViewController之间传值,在这里分享给刚開始学习 ...

  7. HttpUtil工具类,发送Get/Post请求,支持Http和Https协议

    HttpUtil工具类,发送Get/Post请求,支持Http和Https协议 使用用Httpclient封装的HttpUtil工具类,发送Get/Post请求 1. maven引入httpclien ...

  8. AndroidInject项目使用动态代理增加对网络请求的支持

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3540427.html AndroidInject项目是我写的一 ...

  9. Servlet(五):一个Servlet处理多个请求

    一.为什么要使用一个Servlet来处理多个请求? 当浏览器发送了一次请求到服务器时,servlet容器会根据请求的url-pattern找到对应的Servlet类,执行对应的doPost或doGet ...

随机推荐

  1. 数据挖掘算法以及其实现zz

    实验一    分类技术及其应用 实习要求: 基于线性回归模型拟合一个班学生的学习成绩,建立预测模型.数据可由自己建立100个学生的学习成绩. 1)    算法思想: 最小二乘法 设经验方程是y=F(x ...

  2. 基于智能手机的3D地图导航

    https://www.gpsworld.com/resources/archives/ Going 3D Personal Nav and LBS To enrich user experience ...

  3. ADF文件在哪个地方?

    Where is ADF file on Tango Device? Ask Question up vote2down votefavorite   I have a Tango tablet de ...

  4. sitecore 缓存管理器

    namespace XXX.Shared.Infrastructure.Caching { using System; using System.Collections.Generic; using ...

  5. 升级windows 10后网络连接异常

    升级 windows 10,QQ无法连接,显示“登陆超时,请检查网络或者防火墙设置”.打开360软件助手,准备升级QQ试试,360软件助手也显示网络异常. 解决方法: 右键点击开始菜单,命令提示符(管 ...

  6. solr-4.10.2版本使用tomcat7部署

    当前版本仅限于solr-4.10.2版本.默认环境使用的是jdk1.7,tomcat7.环境自己配置.网上一堆堆的. 1.下载相应的文件(solr-4.10.2.zip). 官网地址:http://l ...

  7. Android 异步网络图片加载

    ListView异步加载图片 http://www.eoeandroid.com/forum.php?mod=viewthread&tid=161586 [Android分享] ListVie ...

  8. 初识阿里开源诊断工具Arthas

    上个月,阿里开源了一个名为Arthas的监控工具.恰逢近期自己在写多线程处理业务,由此想到了一个问题. 如果在本机开发调试,IDE可以看到当前的活动线程,例如IntelliJ IDEA,线程是运行还是 ...

  9. 【OCP-12c】CUUG 071题库考试原题及答案解析(17)

    17.(7-11) choose twoView the Exhibit and examine the structure of ORDER_ITEMS and ORDERS tables.You ...

  10. “全栈2019”Java第一百零九章:匿名内部类实现唯一抽象类或接口

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...