You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

503 lines
20 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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对应要上传的NameValue本地文件名</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对应要上传的NameValue本地文件名</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的方法
/// 参数之间用&amp;连接首位没有符号a=1&amp;b=2&amp;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);
}
}
}