# Scm.Http
**Repository Path**: leadiot/scm.http
## Basic Information
- **Project Name**: Scm.Http
- **Description**: 基于.Net的网络请求工具类。
- **Primary Language**: C#
- **License**: MIT
- **Default Branch**: master
- **Homepage**: http://www.c-scm.net
- **GVP Project**: No
## Statistics
- **Stars**: 2
- **Forks**: 2
- **Created**: 2025-11-05
- **Last Updated**: 2026-06-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: net, SCM, Http
## README
# Scm.Http
## 介绍
Scm.Http 是一个轻量级 .NET HTTP 请求工具库,基于 **.NET Standard 2.0** 构建,兼容 .NET Framework 4.6.1+ 及 .NET Core 2.0+ / .NET 5+。
库内提供了同步与异步两套 API,覆盖 **GET、POST、PUT、DELETE** 四种 HTTP 方法,并封装了文件上传(含分片)、文件下载(含断点续传)、MIME 类型识别、URL/Base64 编码等实用功能,帮助开发者以最少的代码完成常见的 HTTP 通信需求。
## 项目结构
```
Scm.Common.Http/
├── Config/
│ ├── CertConfig.cs # HTTPS 证书配置
│ └── ProxyConfig.cs # 代理配置
├── Utils/
│ ├── HttpUtils.cs # HTTP 静态工具方法(核心入口)
│ └── MimeUtils.cs # MIME 类型映射工具
├── HttpConstant.cs # 常量定义(Header、Query 符号等)
├── HttpContentType.cs # Content-Type 常量
├── HttpMethod.cs # HTTP 方法常量(GET/POST/PUT/DELETE)
├── HttpMethodType.cs # HTTP 方法类型(备用)
├── ScmHttpClient.cs # HTTP 客户端(底层请求引擎)
├── ScmHttpParam.cs # 请求参数键值对模型
├── ScmHttpRequest.cs # 请求封装(URL、Header、Body、Query)
└── ScmHttpResponse.cs # 响应封装
```
## 安装
### 方式一:直接引用 DLL
从 `Release` 目录获取 `Scm.Common.Http.dll`,在项目中添加引用即可。
### 方式二:源码引用
将本项目作为子模块或直接复制到解决方案中,通过项目引用添加:
```xml
```
> **注意**:本项目依赖 `Scm.Common.Text.dll`(位于 `Libs/` 目录),用于 JSON 序列化/反序列化。
## 核心类说明
| 类名 | 说明 |
|------|------|
| `ScmHttpClient` | 底层 HTTP 客户端引擎,支持配置 BaseUrl、超时、UserAgent、Cookie、证书等 |
| `ScmHttpRequest` | 请求封装对象,管理 URL、Query 参数、Header、Body 等内容 |
| `ScmHttpParam` | 请求参数键值对模型 |
| `HttpUtils` | **核心工具类**,提供静态便捷方法,覆盖全部 HTTP 操作 |
| `MimeUtils` | MIME 类型工具,支持 100+ 种文件后缀与 MIME 类型互查 |
| `CertConfig` | HTTPS 客户端证书配置 |
| `ProxyConfig` | HTTP 代理配置 |
## 使用说明
### 一、GET 请求
```csharp
// 同步 - 返回字符串
string result = HttpUtils.GetString("https://api.example.com/posts/1");
// 同步 - 返回反序列化对象
var post = HttpUtils.GetObject("https://api.example.com/posts/1");
// 异步 - 返回字符串
string result = await HttpUtils.GetStringAsync("https://api.example.com/posts",
query: new Dictionary { { "userId", "1" } });
// 异步 - 返回反序列化对象
var post = await HttpUtils.GetObjectAsync("https://api.example.com/posts/1");
// 携带自定义请求头
var header = new Dictionary { { "Authorization", "Bearer token" } };
string result = await HttpUtils.GetStringAsync("https://api.example.com/data", header: header);
```
### 二、POST 请求
```csharp
// --- 表单提交 ---
var form = new Dictionary
{
{ "username", "admin" },
{ "password", "123456" }
};
// 同步
string result = HttpUtils.PostFormString("https://api.example.com/login", form);
var user = HttpUtils.PostFormObject("https://api.example.com/login", form);
// 异步
string result = await HttpUtils.PostFormStringAsync("https://api.example.com/login", form);
var user = await HttpUtils.PostFormObjectAsync("https://api.example.com/login", form);
// --- JSON 提交 ---
string json = "{\"title\":\"hello\",\"body\":\"world\",\"userId\":1}";
// 同步
string result = HttpUtils.PostJsonString("https://api.example.com/posts", json);
var post = HttpUtils.PostJsonObject("https://api.example.com/posts", json);
// 异步
string result = await HttpUtils.PostJsonStringAsync("https://api.example.com/posts", json);
var post = await HttpUtils.PostJsonObjectAsync("https://api.example.com/posts", json);
```
### 三、PUT 请求
```csharp
// --- JSON 更新 ---
string json = "{\"id\":1,\"title\":\"updated\",\"body\":\"content\",\"userId\":1}";
// 同步
string result = HttpUtils.PutJsonString("https://api.example.com/posts/1", json);
var post = HttpUtils.PutJsonObject("https://api.example.com/posts/1", json);
// 异步
string result = await HttpUtils.PutJsonStringAsync("https://api.example.com/posts/1", json);
var post = await HttpUtils.PutJsonObjectAsync("https://api.example.com/posts/1", json);
// --- 表单更新 ---
var form = new Dictionary { { "title", "updated" }, { "userId", "1" } };
// 同步
string result = HttpUtils.PutFormString("https://api.example.com/posts/1", form);
// 异步
string result = await HttpUtils.PutFormStringAsync("https://api.example.com/posts/1", form);
var post = await HttpUtils.PutFormObjectAsync("https://api.example.com/posts/1", form);
```
### 四、DELETE 请求
```csharp
// 同步 - 基本删除
string result = HttpUtils.DeleteFormString("https://api.example.com/posts/1");
// 异步 - 基本删除
string result = await HttpUtils.DeleteFormStringAsync("https://api.example.com/posts/1");
// 同步 - 携带 JSON 请求体删除
string result = HttpUtils.DeleteJsonString("https://api.example.com/posts/batch",
json: "{\"ids\":[1,2,3]}");
// 异步 - 携带 JSON 请求体删除并反序列化
var resp = await HttpUtils.DeleteJsonObjectAsync(
"https://api.example.com/posts/batch",
json: "{\"ids\":[1,2,3]}");
```
### 五、文件上传
```csharp
// 整文件上传
string result = HttpUtils.UploadFile(
"https://api.example.com/upload",
filePath: @"D:\photo.jpg",
fileName: "photo.jpg",
fieldName: "file",
form: new Dictionary { { "tag", "avatar" } }
);
// 分片上传(大文件)
using (var stream = File.OpenRead(@"D:\video.mp4"))
{
int chunkSize = 1024 * 1024; // 1MB
var buffer = new byte[chunkSize];
int index = 0;
int read;
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
{
var result = HttpUtils.UploadFile(
"https://api.example.com/upload/chunk",
buffer, 0, read,
fileName: $"{index}.chunk",
fieldName: "file",
form: new Dictionary { { "index", index.ToString() } }
);
index++;
}
}
```
### 六、文件下载
```csharp
// 完整下载
HttpUtils.DownloadFile("https://example.com/file.zip", @"D:\file.zip");
// 断点续传(分片下载)
HttpUtils.DownloadFile("https://example.com/large.mp4", @"D:\part1.mp4",
start: 0, end: 1024 * 1024);
// 异步下载
await HttpUtils.DownloadFileAsync("https://example.com/file.zip", @"D:\file.zip");
```
### 七、底层客户端直接使用
```csharp
var client = new ScmHttpClient("https://api.example.com")
{
Timeout = 5000, // 超时 5 秒
UserAgent = "MyApp/1.0",
AllowAutoRedirect = true
};
var request = new ScmHttpRequest("/data");
request.AddQueryParameter("page", "1");
request.AddHeadParameter("Authorization", "Bearer token");
// GET
string text = client.GetText(request);
byte[] bytes = client.GetByte(request);
// POST
request.ContentType = HttpContentType.APPLICATION_JSON;
request.AddBodyContent("{\"key\":\"value\"}");
string text = client.PostText(request);
// PUT
request.ContentType = HttpContentType.APPLICATION_JSON;
request.AddBodyContent("{\"key\":\"updated\"}");
string text = client.PutText(request);
// DELETE
string text = client.DeleteText(request);
// 异步版本
string text = await client.GetTextAsync(request);
string text = await client.PostTextAsync(request);
string text = await client.PutTextAsync(request);
string text = await client.DeleteTextAsync(request);
```
### 八、MIME 类型工具
```csharp
// 根据后缀获取
string mime = MimeUtils.GetMimeType("pdf"); // → "application/pdf"
string mime = MimeUtils.GetMimeType(".jpg"); // → "image/jpeg"
// 根据文件名获取
string mime = MimeUtils.GetMimeTypeFromFileName("report.xlsx"); // → "...spreadsheetml.sheet"
// 反向查找后缀
string ext = MimeUtils.GetFileExtension("video/mp4"); // → "mp4"
// 注册自定义类型
MimeUtils.RegisterCustomMimeType("wasm", "application/wasm");
```
### 九、公共工具方法
```csharp
// URL 编码
string encoded = HttpUtils.UrlEncode("你好世界");
// Query 字符串构建
var query = new Dictionary { { "a", "1" }, { "b", "2" } };
string url = HttpUtils.BuildQuery(query, "https://api.com/list");
// → "https://api.com/list?a=1&b=2"
// Query 解析
var dict = HttpUtils.Query2Dictionary("a=1&b=2&c=3");
// → { "a":"1", "b":"2", "c":"3" }
// Base64 URL 安全编码
string safe = HttpUtils.ToBase64String(bytes); // 用 -_ 替代 +/
byte[] raw = HttpUtils.FromBase64String(safe); // 还原
// Escape / Unescape
string escaped = HttpUtils.Escape("hello world!");
string unescaped = HttpUtils.Unescape(escaped);
// 网络信息
string ip = HttpUtils.GetIp(); // 获取本机 IPv4
bool isV4 = HttpUtils.IsIPv4("192.168.1.1"); // 判断 IPv4 格式
// HTML / XML 转义
string html = HttpUtils.Db2Html("