准备将园子的部分图片站切换到华为云 CDN,切换前需要解决 CDN 缓存刷新问题。
华为云 CDN 帮助文档列出的 SDK 中没有 .NET 版,原以为华为云没有提供官方 .NET SDK,于是在博问上提问看有没有非官方的 .NET SDK —— 求华为云CDN非官方.NET/C#版SDK。
在园友的回答中惊喜地知道,原来华为云已经提供官方 .NET SDK —— Huawei Cloud .Net SDK,惊喜之余让人失望的是没有 CDN 部分的实现,庆幸的是认证鉴权部分已经在 HuaweiCloud.SDK.Core 中实现,自己写代码调用 CDN api 的工作量小了很多。
分享一下初步的实现代码。
首先,创建 .NET 6 控制台程序并安装 nuget 包 HuaweiCloud.SDK.Core
dotnet new console
dotnet add package HuaweiCloud.SDK.Core
接下来,创建 CdnClient 类并实现刷新缓存的异步方法 RefreshAsync
public class CdnClient : Client
{
public async Task<bool> RefreshAsync(params string[] urls)
{
SdkRequest request = HttpUtils.InitSdkRequest(
"v1.0/cdn/content/refresh-tasks",
"application/json;charset=UTF-8");
var data = new {
refresh_task = new
{
type = "file",
urls = urls
}
};
request.Body = JsonSerializer.Serialize(data);
var response = await DoHttpRequestAsync("POST", request);
if (response.IsSuccessStatusCode)
{
var resultType = new { refresh_task = "" }.GetType();
dynamic? result = await response.Content.ReadFromJsonAsync(resultType);
return int.TryParse(result?.refresh_task, out int taskId) && taskId > 0;
}
return false;
}
}
最后,Program 中调用 CdnClient 刷新缓存
using huawei_cloud_cdn;
using HuaweiCloud.SDK.Core;
using HuaweiCloud.SDK.Core.Auth;
using Microsoft.Extensions.Logging;
using static HuaweiCloud.SDK.Core.Client;
const string ak = "我的凭证 -> 访问密钥 -> Access Key Id";
const string sk = "我的凭证 -> 访问密钥 -> Secret Access Key";
const string endpoint = "https://cdn.myhuaweicloud.com/";
const string projectId = "我的凭证 -> API凭证 -> 项目ID";
var auth = new BasicCredentials(ak, sk, projectId);
var config = HttpConfig.GetDefaultConfig();
config.IgnoreSslVerification = true;
var cdnClient = new ClientBuilder<CdnClient>()
.WithCredential(auth)
.WithEndPoint(endpoint)
.WithHttpConfig(config)
.WithLogging(LogLevel.Information)
.Build();
var url = "https://common.cnblogs.com/logo.png";
var success = await cdnClient.RefreshAsync(url);
Console.WriteLine($"{(success ? "succeed": "fail")} to refresh {url}");
运行后成功刷新缓存。
$ dotnet run
info: System.Net.Http.HttpClient.SdkHttpClient.LogicalHandler[100]
Start processing HTTP request POST https://cdn.myhuaweicloud.com/v1.0/cdn/content/refresh-tasks
info: System.Net.Http.HttpClient.SdkHttpClient.ClientHandler[100]
Sending HTTP request POST https://cdn.myhuaweicloud.com/v1.0/cdn/content/refresh-tasks
info: System.Net.Http.HttpClient.SdkHttpClient.ClientHandler[101]
Received HTTP response after 2271.4836ms - OK
info: System.Net.Http.HttpClient.SdkHttpClient.LogicalHandler[101]
End processing HTTP request after 2301.9488ms - OK
succeed to refresh https://common.cnblogs.com/logo.png
实现过程中走了一个弯路,开始用下面的代码反序列化响应的 json 内容
var result = await response.Content.ReadFromJsonAsync<dynamic>();
return int.TryParse(result?.refresh_task, out int taskId) && taskId > 0;
运行时报错
'System.Text.Json.JsonElement' does not contain a definition for 'refresh_task'
原来是 System.Text.Json 不支持这样反序列化匿名类型,反序列化的结果还是原来的 json 字符串。
后来改为下面的代码解决了。
var resultType = new { refresh_task = "" }.GetType();
dynamic? result = await response.Content.ReadFromJsonAsync(resultType);
return int.TryParse(result?.refresh_task, out int taskId) && taskId > 0;