Files
2024-06-21 12:27:15 +08:00

308 lines
10 KiB
C#
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#region Copyright (C) 2016 Kevin (OSS开源系列) 公众号:osscore
/***************************************************************************
*   文件功能描述:Http请求 == 主请求实体
*
*   创建人: Kevin
* 创建人Email:1985088337@qq.com
*
*****************************************************************************/
#endregion
using System.Net;
using System.Text;
namespace OSS.Tools.Http
{
/// <summary>
/// 请求基类
/// </summary>
public static class HttpClientExtension
{
private const string _lineBreak = "\r\n";
/// <summary>
/// 编码格式
/// </summary>
internal static Encoding Encoding { get; set; } = Encoding.UTF8;
#region 扩展方法
/// <summary>
/// 执行请求方法
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <returns></returns>
public static Task<HttpResponseMessage> SendAsync(this HttpClient? client, OssHttpRequest request)
{
return SendAsync(client, request, HttpCompletionOption.ResponseContentRead, CancellationToken.None);
}
/// <summary>
/// 执行请求方法
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="completionOption"></param>
/// <returns></returns>
public static Task<HttpResponseMessage> SendAsync(this HttpClient? client, OssHttpRequest request,
HttpCompletionOption completionOption)
{
return SendAsync(client, request, completionOption, CancellationToken.None);
}
/// <summary>
/// 执行请求方法
/// </summary>
/// <param name="client"></param>
/// <param name="request"></param>
/// <param name="completionOption"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
public static async Task<HttpResponseMessage> SendAsync(this HttpClient? client, OssHttpRequest request,
HttpCompletionOption completionOption,
CancellationToken cancellationToken)
{
request.PrepareSend();
await request.PrepareSendAsync();
var reqMsg = new HttpRequestMessage
{
RequestUri = new Uri(request.address_url),
Method = request.http_method
};
PackageReqContent(reqMsg, request); // 配置内容
request.OnSending(reqMsg);
await request.OnSendingAsync(reqMsg);
return await client.SendAsync(reqMsg, completionOption, cancellationToken);
}
/// <summary>
/// 读取响应内容中的字符串
/// </summary>
/// <param name="taskResp"></param>
/// <param name="disposeResponse"></param>
/// <returns></returns>
public static async Task<string> ReadContentAsStringAsync(this Task<HttpResponseMessage> taskResp, bool disposeResponse = true)
{
var resp = await taskResp;
return await ReadContentAsStringAsync(resp, disposeResponse);
}
/// <summary>
/// 读取响应内容中的字符串
/// </summary>
/// <param name="resp"></param>
/// <param name="disposeResponse"></param>
/// <returns></returns>
public static async Task<string> ReadContentAsStringAsync(this HttpResponseMessage resp, bool disposeResponse = true)
{
var resStr = string.Empty;
if (resp.StatusCode != HttpStatusCode.NoContent)
{
resStr = await resp .Content.ReadAsStringAsync();
}
if (disposeResponse)
{
resp.Dispose();
}
return resStr;
}
#endregion
#region 配置 ReqMsg信息
/// <summary>
/// 配置使用的content
/// </summary>
/// <param name="reqMsg"></param>
/// <param name="req"></param>
/// <returns></returns>
private static void PackageReqContent(HttpRequestMessage reqMsg, OssHttpRequest req)
{
if (!string.IsNullOrEmpty(req.HeaderAuthorization))
{
reqMsg.Headers.Remove("Authorization");
reqMsg.Headers.TryAddWithoutValidation("Authorization", req.HeaderAuthorization);
}
if (req.http_method == HttpMethod.Get)
return;
if (req.file_paras!=null&& req.file_paras.Any())
{
var boundary =GetBoundary();
var memory=new MemoryStream();
WriteMultipartFormData(memory, req, boundary);
memory.Seek(0, SeekOrigin.Begin);//设置指针到起点
reqMsg.Content = new StreamContent(memory);
//req.RequestSet?.Invoke(reqMsg);
reqMsg.Content.Headers.Remove("Content-Type");
reqMsg.Content.Headers.TryAddWithoutValidation("Content-Type", $"multipart/form-data;boundary={boundary}");
}
else
{
var data = GetNormalFormData(req);
if (!string.IsNullOrEmpty(data))
{
// 默认表单提交,上层应用程序可以设置
reqMsg.Content = new StringContent(data, Encoding.UTF8, "application/x-www-form-urlencoded");
}
}
}
#endregion
#region 请求数据的 内容 处理
#region 处理带文件上传的数据处理
/// <summary>
/// 写入 Form 的内容值 【 非文件参数 + 文件头 + 文件参数(内部完成) + 请求结束符 】
/// </summary>
/// <param name="memory"></param>
/// <param name="request"></param>
/// <param name="boundary"></param>
private static void WriteMultipartFormData(Stream memory, OssHttpRequest request, string boundary)
{
if (request.form_paras != null)
{
foreach (var param in request.form_paras)
{
WriteStringTo(memory, GetMultipartFormData(param, boundary));
}
}
if (request.file_paras != null){
foreach (var file in request.file_paras)
{
//文件头
WriteStringTo(memory, GetMultipartFileHeader(file, boundary));
//文件内容
file.Writer(memory);
//文件结尾
WriteStringTo(memory, _lineBreak);
}
}
//写入整个请求的底部信息
WriteStringTo(memory, GetMultipartFooter(boundary));
}
/// <summary>
/// 写入 Form 的内容值(文件头)
/// </summary>
/// <param name="file"></param>
/// <param name="boundary"></param>
/// <returns></returns>
private static string GetMultipartFileHeader(FileParameter file, string boundary)
{
var conType = file.ContentType ?? "application/octet-stream";
return $"--{boundary}{_lineBreak}Content-Disposition: form-data; name=\"{file.Name}\"; filename=\"{file.FileName}\"{_lineBreak}Content-Type: {conType}{_lineBreak}{_lineBreak}";
}
/// <summary>
/// 写入 Form 的内容值(非文件参数)
/// </summary>
/// <param name="param"></param>
/// <param name="boundary"></param>
/// <returns></returns>
private static string GetMultipartFormData(NameValuePair param, string boundary)
{
return
$"--{boundary}{_lineBreak}Content-Disposition: form-data; name=\"{param.name}\"{_lineBreak}{_lineBreak}{param.value}{_lineBreak}";
}
/// <summary>
/// 写入 Form 的内容值 (请求结束符)
/// </summary>
/// <param name="boundary"></param>
/// <returns></returns>
private static string GetMultipartFooter(string boundary)
{
return $"--{boundary}--{_lineBreak}";
}
#endregion
#region 不包含文件的数据处理(正常 get/post 请求)
/// <summary>
/// 写入请求的内容信息 (非文件上传请求)
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
private static string GetNormalFormData(OssHttpRequest request)
{
var formString = new StringBuilder();
if (request.form_paras != null)
{
foreach (var p in request.form_paras)
{
if (formString.Length > 1)
formString.Append("&");
formString.AppendFormat(p.ToString());
}
}
if (string.IsNullOrEmpty(request.custom_body))
return formString.ToString();
if (formString.Length > 1)
formString.Append("&");
formString.Append(request.custom_body);
return formString.ToString();
}
#endregion
#endregion
#region 请求辅助方法
/// <summary>
/// 写入数据方法(将数据写入 request)
/// </summary>
/// <param name="stream"></param>
/// <param name="toWrite"></param>
/// <returns>写入的字节数量</returns>
private static void WriteStringTo(Stream stream, string toWrite)
{
var bytes = Encoding.GetBytes(toWrite);
stream.Write(bytes, 0, bytes.Length);
}
/// <summary>
/// 创建 请求 分割界限
/// </summary>
/// <returns></returns>
private static string GetBoundary()
{
const string pattern = "abcdefghijklmnopqrstuvwxyz0123456789";
var boundaryBuilder = new StringBuilder();
var rnd = new Random();
for (var i = 0; i < 10; i++)
{
var index = rnd.Next(pattern.Length);
boundaryBuilder.Append(pattern[index]);
}
return $"-------{boundaryBuilder}";
}
#endregion
}
}