|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
using System.IO;
|
|
|
using System.Linq;
|
|
|
using System.Net;
|
|
|
using System.Net.Security;
|
|
|
using System.Security.Cryptography.X509Certificates;
|
|
|
using System.Text;
|
|
|
|
|
|
namespace POSV.Utils
|
|
|
{
|
|
|
/// <summary>
|
|
|
/// HTTP 请求工具类
|
|
|
/// </summary>
|
|
|
public static class RequestUtility
|
|
|
{
|
|
|
#region 代理
|
|
|
|
|
|
private static WebProxy _webproxy = null;
|
|
|
|
|
|
/// <summary>
|
|
|
/// 设置Web代理
|
|
|
/// </summary>
|
|
|
/// <param name="host"></param>
|
|
|
/// <param name="port"></param>
|
|
|
/// <param name="username"></param>
|
|
|
/// <param name="password"></param>
|
|
|
public static void SetHttpProxy(string host , string port , string username , string password)
|
|
|
{
|
|
|
ICredentials cred;
|
|
|
cred = new NetworkCredential(username , password);
|
|
|
if (!string.IsNullOrEmpty(host))
|
|
|
{
|
|
|
_webproxy = new WebProxy(host + ":" + port ?? "80" , true , null , cred);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 清除Web代理状态
|
|
|
/// </summary>
|
|
|
public static void RemoveHttpProxy()
|
|
|
{
|
|
|
_webproxy = null;
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region 同步方法
|
|
|
|
|
|
#region Get
|
|
|
|
|
|
/// <summary>
|
|
|
/// 使用Get方法获取字符串结果(没有加入Cookie)
|
|
|
/// </summary>
|
|
|
/// <param name="url"></param>
|
|
|
/// <returns></returns>
|
|
|
public static string HttpGet(string url , Encoding encoding = null)
|
|
|
{
|
|
|
WebClient wc = new WebClient();
|
|
|
wc.Proxy = _webproxy;
|
|
|
wc.Encoding = encoding ?? Encoding.UTF8;
|
|
|
return wc.DownloadString(url);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 使用Get方法获取字符串结果(加入Cookie)
|
|
|
/// </summary>
|
|
|
/// <param name="url"></param>
|
|
|
/// <param name="cookieContainer"></param>
|
|
|
/// <param name="encoding"></param>
|
|
|
/// <param name="cer">证书,如果不需要则保留null</param>
|
|
|
/// <param name="timeOut"></param>
|
|
|
/// <returns></returns>
|
|
|
public static string HttpGet(string url , CookieContainer cookieContainer = null , Encoding encoding = null , X509Certificate2 cer = null , int timeOut = Constant.TIMEOUT)
|
|
|
{
|
|
|
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
|
|
request.Method = "GET";
|
|
|
request.Timeout = timeOut;
|
|
|
request.Proxy = _webproxy;
|
|
|
if (cer != null)
|
|
|
{
|
|
|
request.ClientCertificates.Add(cer);
|
|
|
}
|
|
|
|
|
|
if (cookieContainer != null)
|
|
|
{
|
|
|
request.CookieContainer = cookieContainer;
|
|
|
}
|
|
|
|
|
|
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
|
|
|
|
|
if (cookieContainer != null)
|
|
|
{
|
|
|
response.Cookies = cookieContainer.GetCookies(response.ResponseUri);
|
|
|
}
|
|
|
|
|
|
using (Stream responseStream = response.GetResponseStream())
|
|
|
{
|
|
|
using (StreamReader myStreamReader = new StreamReader(responseStream , encoding ?? Encoding.GetEncoding("utf-8")))
|
|
|
{
|
|
|
string retString = myStreamReader.ReadToEnd();
|
|
|
return retString;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
#region Post
|
|
|
|
|
|
/// <summary>
|
|
|
/// 使用Post方法获取字符串结果,常规提交
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public static string HttpPost(string url , CookieContainer cookieContainer = null , Dictionary<string , string> formData = null , Encoding encoding = null , X509Certificate2 cer = null , int timeOut = Constant.TIMEOUT)
|
|
|
{
|
|
|
MemoryStream ms = new MemoryStream();
|
|
|
formData.FillFormDataStream(ms);//填充formData
|
|
|
return HttpPost(url , cookieContainer , ms , null , null , encoding , cer , timeOut);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 使用Post方法获取字符串结果
|
|
|
/// </summary>
|
|
|
/// <param name="url"></param>
|
|
|
/// <param name="cookieContainer"></param>
|
|
|
/// <param name="postStream"></param>
|
|
|
/// <param name="fileDictionary">需要上传的文件,Key:对应要上传的Name,Value:本地文件名</param>
|
|
|
/// <param name="encoding"></param>
|
|
|
/// <param name="cer">证书,如果不需要则保留null</param>
|
|
|
/// <param name="timeOut"></param>
|
|
|
/// <param name="checkValidationResult">验证服务器证书回调自动验证</param>
|
|
|
/// <param name="refererUrl"></param>
|
|
|
/// <returns></returns>
|
|
|
public static string HttpPost(string url , CookieContainer cookieContainer = null , Stream postStream = null , Dictionary<string , string> fileDictionary = null , string refererUrl = null , Encoding encoding = null , X509Certificate2 cer = null , int timeOut = Constant.TIMEOUT , bool checkValidationResult = false)
|
|
|
{
|
|
|
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
|
|
request.Method = "POST";
|
|
|
request.Timeout = timeOut;
|
|
|
request.Proxy = _webproxy;
|
|
|
if (cer != null)
|
|
|
{
|
|
|
request.ClientCertificates.Add(cer);
|
|
|
}
|
|
|
|
|
|
if (checkValidationResult)
|
|
|
{
|
|
|
ServicePointManager.ServerCertificateValidationCallback =
|
|
|
new RemoteCertificateValidationCallback(CheckValidationResult);
|
|
|
}
|
|
|
|
|
|
#region 处理Form表单文件上传
|
|
|
var formUploadFile = fileDictionary != null && fileDictionary.Count > 0;//是否用Form上传文件
|
|
|
if (formUploadFile)
|
|
|
{
|
|
|
//通过表单上传文件
|
|
|
postStream = postStream ?? new MemoryStream();
|
|
|
|
|
|
string boundary = "----" + DateTime.Now.Ticks.ToString("x");
|
|
|
//byte[] boundarybytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
|
|
|
string fileFormdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n";
|
|
|
string dataFormdataTemplate = "\r\n--" + boundary +
|
|
|
"\r\nContent-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
|
|
|
foreach (var file in fileDictionary)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
var fileName = file.Value;
|
|
|
//准备文件流
|
|
|
using (var fileStream = FileHelper.GetFileStream(fileName))
|
|
|
{
|
|
|
string formdata = null;
|
|
|
if (fileStream != null)
|
|
|
{
|
|
|
//存在文件
|
|
|
formdata = string.Format(fileFormdataTemplate , file.Key , /*fileName*/ Path.GetFileName(fileName));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//不存在文件或只是注释
|
|
|
formdata = string.Format(dataFormdataTemplate , file.Key , file.Value);
|
|
|
}
|
|
|
|
|
|
//统一处理
|
|
|
var formdataBytes = Encoding.UTF8.GetBytes(postStream.Length == 0 ? formdata.Substring(2 , formdata.Length - 2) : formdata);//第一行不需要换行
|
|
|
postStream.Write(formdataBytes , 0 , formdataBytes.Length);
|
|
|
|
|
|
//写入文件
|
|
|
if (fileStream != null)
|
|
|
{
|
|
|
byte[] buffer = new byte[1024];
|
|
|
int bytesRead = 0;
|
|
|
while ((bytesRead = fileStream.Read(buffer , 0 , buffer.Length)) != 0)
|
|
|
{
|
|
|
postStream.Write(buffer , 0 , bytesRead);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
throw ex;
|
|
|
}
|
|
|
}
|
|
|
//结尾
|
|
|
var footer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
|
|
|
postStream.Write(footer , 0 , footer.Length);
|
|
|
|
|
|
request.ContentType = string.Format("multipart/form-data; boundary={0}" , boundary);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
request.ContentType = "application/x-www-form-urlencoded";
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
request.ContentLength = postStream != null ? postStream.Length : 0;
|
|
|
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
|
|
|
request.KeepAlive = true;
|
|
|
|
|
|
if (!string.IsNullOrEmpty(refererUrl))
|
|
|
{
|
|
|
request.Referer = refererUrl;
|
|
|
}
|
|
|
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36";
|
|
|
|
|
|
if (cookieContainer != null)
|
|
|
{
|
|
|
request.CookieContainer = cookieContainer;
|
|
|
}
|
|
|
|
|
|
#region 输入二进制流
|
|
|
if (postStream != null)
|
|
|
{
|
|
|
postStream.Position = 0;
|
|
|
|
|
|
//直接写入流
|
|
|
Stream requestStream = request.GetRequestStream();
|
|
|
|
|
|
byte[] buffer = new byte[1024];
|
|
|
int bytesRead = 0;
|
|
|
while ((bytesRead = postStream.Read(buffer , 0 , buffer.Length)) != 0)
|
|
|
{
|
|
|
requestStream.Write(buffer , 0 , bytesRead);
|
|
|
}
|
|
|
|
|
|
//debug
|
|
|
//postStream.Seek(0, SeekOrigin.Begin);
|
|
|
//StreamReader sr = new StreamReader(postStream);
|
|
|
//var postStr = sr.ReadToEnd();
|
|
|
|
|
|
postStream.Close();//关闭文件访问
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
|
|
|
|
|
if (cookieContainer != null)
|
|
|
{
|
|
|
response.Cookies = cookieContainer.GetCookies(response.ResponseUri);
|
|
|
}
|
|
|
|
|
|
using (Stream responseStream = response.GetResponseStream())
|
|
|
{
|
|
|
using (StreamReader myStreamReader = new StreamReader(responseStream , encoding ?? Encoding.GetEncoding("utf-8")))
|
|
|
{
|
|
|
string retString = myStreamReader.ReadToEnd();
|
|
|
return retString;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 使用Post方法获取字符串结果
|
|
|
/// </summary>
|
|
|
/// <param name="url"></param>
|
|
|
/// <param name="cookieContainer"></param>
|
|
|
/// <param name="postStream"></param>
|
|
|
/// <param name="fileDictionary">需要上传的文件,Key:对应要上传的Name,Value:本地文件名</param>
|
|
|
/// <param name="encoding"></param>
|
|
|
/// <param name="cer">证书,如果不需要则保留null</param>
|
|
|
/// <param name="timeOut"></param>
|
|
|
/// <param name="checkValidationResult">验证服务器证书回调自动验证</param>
|
|
|
/// <param name="refererUrl"></param>
|
|
|
/// <returns></returns>
|
|
|
public static string HttpPostCCB(string url, CookieContainer cookieContainer = null, Stream postStream = null, Dictionary<string, string> fileDictionary = null, string refererUrl = null, Encoding encoding = null, X509Certificate2 cer = null, int timeOut = Constant.TIMEOUT, bool checkValidationResult = false)
|
|
|
{
|
|
|
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
|
|
request.Method = "POST";
|
|
|
request.Timeout = timeOut;
|
|
|
request.Proxy = _webproxy;
|
|
|
if (cer != null)
|
|
|
{
|
|
|
request.ClientCertificates.Add(cer);
|
|
|
}
|
|
|
|
|
|
if (checkValidationResult)
|
|
|
{
|
|
|
ServicePointManager.ServerCertificateValidationCallback =
|
|
|
new RemoteCertificateValidationCallback(CheckValidationResult);
|
|
|
}
|
|
|
|
|
|
#region 处理Form表单文件上传
|
|
|
var formUploadFile = fileDictionary != null && fileDictionary.Count > 0;//是否用Form上传文件
|
|
|
if (formUploadFile)
|
|
|
{
|
|
|
//通过表单上传文件
|
|
|
postStream = postStream ?? new MemoryStream();
|
|
|
|
|
|
string boundary = "----" + DateTime.Now.Ticks.ToString("x");
|
|
|
//byte[] boundarybytes = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
|
|
|
string fileFormdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n";
|
|
|
string dataFormdataTemplate = "\r\n--" + boundary +
|
|
|
"\r\nContent-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
|
|
|
foreach (var file in fileDictionary)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
var fileName = file.Value;
|
|
|
//准备文件流
|
|
|
using (var fileStream = FileHelper.GetFileStream(fileName))
|
|
|
{
|
|
|
string formdata = null;
|
|
|
if (fileStream != null)
|
|
|
{
|
|
|
//存在文件
|
|
|
formdata = string.Format(fileFormdataTemplate, file.Key, /*fileName*/ Path.GetFileName(fileName));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
//不存在文件或只是注释
|
|
|
formdata = string.Format(dataFormdataTemplate, file.Key, file.Value);
|
|
|
}
|
|
|
|
|
|
//统一处理
|
|
|
var formdataBytes = Encoding.UTF8.GetBytes(postStream.Length == 0 ? formdata.Substring(2, formdata.Length - 2) : formdata);//第一行不需要换行
|
|
|
postStream.Write(formdataBytes, 0, formdataBytes.Length);
|
|
|
|
|
|
//写入文件
|
|
|
if (fileStream != null)
|
|
|
{
|
|
|
byte[] buffer = new byte[1024];
|
|
|
int bytesRead = 0;
|
|
|
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
|
|
|
{
|
|
|
postStream.Write(buffer, 0, bytesRead);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
throw ex;
|
|
|
}
|
|
|
}
|
|
|
//结尾
|
|
|
var footer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
|
|
|
postStream.Write(footer, 0, footer.Length);
|
|
|
|
|
|
request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
request.ContentType = "application/x-www-form-urlencoded";
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
request.ContentLength = postStream != null ? postStream.Length : 0;
|
|
|
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
|
|
|
request.KeepAlive = false;
|
|
|
request.ProtocolVersion = new Version(1, 0);
|
|
|
|
|
|
if (!string.IsNullOrEmpty(refererUrl))
|
|
|
{
|
|
|
request.Referer = refererUrl;
|
|
|
}
|
|
|
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36";
|
|
|
|
|
|
if (cookieContainer != null)
|
|
|
{
|
|
|
request.CookieContainer = cookieContainer;
|
|
|
}
|
|
|
|
|
|
#region 输入二进制流
|
|
|
if (postStream != null)
|
|
|
{
|
|
|
postStream.Position = 0;
|
|
|
|
|
|
//直接写入流
|
|
|
Stream requestStream = request.GetRequestStream();
|
|
|
|
|
|
byte[] buffer = new byte[1024];
|
|
|
int bytesRead = 0;
|
|
|
while ((bytesRead = postStream.Read(buffer, 0, buffer.Length)) != 0)
|
|
|
{
|
|
|
requestStream.Write(buffer, 0, bytesRead);
|
|
|
}
|
|
|
|
|
|
//debug
|
|
|
//postStream.Seek(0, SeekOrigin.Begin);
|
|
|
//StreamReader sr = new StreamReader(postStream);
|
|
|
//var postStr = sr.ReadToEnd();
|
|
|
|
|
|
postStream.Close();//关闭文件访问
|
|
|
}
|
|
|
#endregion
|
|
|
|
|
|
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
|
|
|
|
|
if (cookieContainer != null)
|
|
|
{
|
|
|
response.Cookies = cookieContainer.GetCookies(response.ResponseUri);
|
|
|
}
|
|
|
|
|
|
using (Stream responseStream = response.GetResponseStream())
|
|
|
{
|
|
|
using (StreamReader myStreamReader = new StreamReader(responseStream, encoding ?? Encoding.GetEncoding("GB18030")))
|
|
|
{
|
|
|
string retString = myStreamReader.ReadToEnd();
|
|
|
return retString;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
|
/// 验证服务器证书
|
|
|
/// </summary>
|
|
|
/// <param name="sender"></param>
|
|
|
/// <param name="certificate"></param>
|
|
|
/// <param name="chain"></param>
|
|
|
/// <param name="errors"></param>
|
|
|
/// <returns></returns>
|
|
|
private static bool CheckValidationResult(object sender , X509Certificate certificate , X509Chain chain , SslPolicyErrors errors)
|
|
|
{
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
/// <summary>
|
|
|
/// 组装QueryString的方法
|
|
|
/// 参数之间用&连接,首位没有符号,如:a=1&b=2&c=3
|
|
|
/// </summary>
|
|
|
/// <param name="formData"></param>
|
|
|
/// <returns></returns>
|
|
|
public static string GetQueryString(this Dictionary<string , string> formData)
|
|
|
{
|
|
|
if (formData == null || formData.Count == 0)
|
|
|
{
|
|
|
return "";
|
|
|
}
|
|
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
var i = 0;
|
|
|
foreach (var kv in formData)
|
|
|
{
|
|
|
i++;
|
|
|
sb.AppendFormat("{0}={1}" , kv.Key , kv.Value);
|
|
|
if (i < formData.Count)
|
|
|
{
|
|
|
sb.Append("&");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
return sb.ToString();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 填充表单信息的Stream
|
|
|
/// </summary>
|
|
|
/// <param name="formData"></param>
|
|
|
/// <param name="stream"></param>
|
|
|
public static void FillFormDataStream(this Dictionary<string , string> formData , Stream stream)
|
|
|
{
|
|
|
string dataString = GetQueryString(formData);
|
|
|
var formDataBytes = formData == null ? new byte[0] : Encoding.UTF8.GetBytes(dataString);
|
|
|
stream.Write(formDataBytes , 0 , formDataBytes.Length);
|
|
|
stream.Seek(0 , SeekOrigin.Begin);//设置指针读取位置
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// <para>将 URL 中的参数名称/值编码为合法的格式。</para>
|
|
|
/// <para>可以解决类似这样的问题:假设参数名为 tvshow, 参数值为 Tom&Jerry,如果不编码,可能得到的网址: http://a.com/?tvshow=Tom&Jerry&year=1965 编码后则为:http://a.com/?tvshow=Tom%26Jerry&year=1965 </para>
|
|
|
/// <para>实践中经常导致问题的字符有:'&', '?', '=' 等</para>
|
|
|
/// </summary>
|
|
|
/// <param name="data"></param>
|
|
|
/// <returns></returns>
|
|
|
public static string AsUrlData(this string data)
|
|
|
{
|
|
|
if (data == null)
|
|
|
{
|
|
|
return null;
|
|
|
}
|
|
|
return Uri.EscapeDataString(data);
|
|
|
}
|
|
|
}
|
|
|
}
|