oss 无dns下载实现

This commit is contained in:
zzz
2025-06-16 21:17:33 +08:00
parent 30648e1f11
commit 369be0032e

197
Form1.cs
View File

@@ -122,16 +122,15 @@ namespace CheckDownload
{
try
{
//const int totalSteps = 4;
//int currentStep = 0;
UpdateStatus("下载在线MD5文件并读取...");
OssClient client = new OssClient(OssEndpoint, OssAccessKeyId, OssAccessKeySecret);
var obj = client.GetObject(OssBucketName, Md5File);
string tempFilePath = Path.Combine(_tempDirectory, Md5File);
using (var fileStream = File.Create(tempFilePath))
// 使用带备用方案的下载方法
if (!await DownloadFileWithFallback(Md5File, tempFilePath))
{
obj.Content.CopyTo(fileStream);
UpdateStatus("下载在线MD5文件失败");
await Task.Delay(3000);
this.Close();
return;
}
var onlineData = ReadOnlineMd5File(tempFilePath);
if (!ValidateOnlineData(onlineData.Version, onlineData.Md5, onlineData.Data))
@@ -296,6 +295,29 @@ namespace CheckDownload
UpdateProgressValue(progress);
UpdateStatus($"已下载 {_completedCount}/{_totalCount}");
}
catch (Exception ex) when (ex is OssException || ex is WebException)
{
UpdateStatus($"使用备用方案尝试...");
string ossKey = $"File/{expectedMd5}";
string tempFilePath = Path.Combine(_tempDirectory, filePath);
bool fallbackResult = DownloadWithFallback(ossKey, tempFilePath);
if (fallbackResult)
{
Interlocked.Increment(ref _completedCount);
int progress = (int)((double)_completedCount / _totalCount * 95);
UpdateProgressValue(progress);
UpdateStatus($"已下载 {_completedCount}/{_totalCount}");
// 记录文件信息
lock (_downloadedFiles)
{
_downloadedFiles[filePath] = (null, expectedMd5);
}
}
else
{
UpdateStatus($"备用方案已执行");
}
}
catch (Exception ex)
{
UpdateStatus($"下载文件 {filePath} 失败: {ex.Message}");
@@ -317,6 +339,89 @@ namespace CheckDownload
}
}
private async Task<List<string>> GetIpAddressesForDomain(string domain)
{
try
{
using (var httpClient = new HttpClient())
{
var request = new HttpRequestMessage(HttpMethod.Get, $"https://223.5.5.5/resolve?name={domain}&type=1&short=1");
request.Headers.Add("User-Agent", "Apifox/1.0.0 (https://apifox.com)");
request.Headers.Add("Accept", "*/*");
request.Headers.Host = "223.5.5.5";
request.Headers.Add("Connection", "keep-alive");
var response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<List<string>>(responseBody);
}
}
catch (Exception ex)
{
UpdateStatus($"获取域名IP失败: {domain} - {ex.Message}");
return new List<string>();
}
}
private bool DownloadWithFallback(string ossKey, string localPath)
{
try
{
UpdateStatus($"备用方案开始下载...");
// 1. 用 SDK 生成带签名的 URL
OssClient fallbackClient = new OssClient(OssEndpoint, OssAccessKeyId, OssAccessKeySecret);
var req = new GeneratePresignedUriRequest(OssBucketName, ossKey, SignHttpMethod.Get)
{
Expiration = DateTime.Now.AddMinutes(10)
};
var signedUrl = fallbackClient.GeneratePresignedUri(req).ToString();
var signedUri = new Uri(signedUrl);
var domain = signedUri.Host;
List<string> ips = GetIpAddressesForDomain(domain).GetAwaiter().GetResult();
if (ips == null || ips.Count == 0)
{
UpdateStatus($"备用方案无法获取IP地址");
return false;
}
foreach (var ip in ips)
{
try
{
var ipUrl = signedUrl.Replace(signedUri.Host, ip);
using (var httpClient = new HttpClient())
{
var request = new HttpRequestMessage(HttpMethod.Get, ipUrl);
request.Headers.Host = signedUri.Host;
var response = httpClient.SendAsync(request).GetAwaiter().GetResult();
response.EnsureSuccessStatusCode();
byte[] fileData = response.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult();
string localDir = Path.GetDirectoryName(localPath);
if (!Directory.Exists(localDir))
{
Directory.CreateDirectory(localDir);
}
File.WriteAllBytes(localPath, fileData);
UpdateStatus($"备用方案下载成功");
return true;
}
}
catch (Exception ex)
{
UpdateStatus($"备用方案用IP下载失败");
}
}
UpdateStatus($"备用方案所有IP均尝试失败");
return false;
}
catch (Exception ex)
{
UpdateStatus($"备用方案下载失败");
return false;
}
}
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetProcessHandleCount(IntPtr hProcess, out uint pdwHandleCount);
@@ -406,7 +511,7 @@ namespace CheckDownload
catch (IOException)
{
// 文件被占用,尝试解锁
UpdateStatus($"文件 {Path.GetFileName(targetPath)} 被占用,尝试解锁...");
UpdateStatus($"文件被占用,尝试解锁...");
try
{
@@ -426,7 +531,7 @@ namespace CheckDownload
processName.Contains("chrome") ||
processName.Contains("edge") ||
processName.Contains("firefox") ||
processName.Contains("iexplore") ||
processName.Contains("ieplore") ||
processName.Contains("winword") ||
processName.Contains("excel") ||
processName.Contains("powerpnt") ||
@@ -466,7 +571,7 @@ namespace CheckDownload
// 再次尝试移动文件
Thread.Sleep(500); // 等待一段时间确保文件已释放
File.Move(sourcePath, targetPath);
UpdateStatus($"文件 {Path.GetFileName(targetPath)} 解锁成功并已更新");
UpdateStatus($"文件解锁成功并已更新");
return true;
}
catch
@@ -668,5 +773,77 @@ namespace CheckDownload
return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
}
}
// 通用的带备用方案的 OSS 文件下载方法
private async Task<bool> DownloadFileWithFallback(string ossKey, string localPath)
{
// 1. 先尝试用 OSS SDK 下载
try
{
OssClient client = new OssClient(OssEndpoint, OssAccessKeyId, OssAccessKeySecret);
var obj = client.GetObject(OssBucketName, ossKey);
string localDir = Path.GetDirectoryName(localPath);
if (!Directory.Exists(localDir))
{
Directory.CreateDirectory(localDir);
}
using (var fileStream = File.Create(localPath))
{
obj.Content.CopyTo(fileStream);
}
return true;
}
catch (Exception ex) when (ex is OssException || ex is WebException || ex is IOException)
{
UpdateStatus($"主下载失败,尝试备用方案...");
}
// 2. 备用方案:用 IP 下载带签名URL
var domain = new Uri("https://" + OssEndpoint).Host;
List<string> ips = await GetIpAddressesForDomain(domain);
if (ips == null || ips.Count == 0)
{
UpdateStatus($"无法获取IP地址");
return false;
}
// 用 SDK 生成带签名的 URL
OssClient fallbackClient = new OssClient(OssEndpoint, OssAccessKeyId, OssAccessKeySecret);
var req = new GeneratePresignedUriRequest(OssBucketName, ossKey, SignHttpMethod.Get)
{
Expiration = DateTime.Now.AddMinutes(10)
};
var signedUrl = fallbackClient.GeneratePresignedUri(req).ToString();
var signedUri = new Uri(signedUrl);
foreach (var ip in ips)
{
try
{
// 替换URL中的host为IP
var ipUrl = signedUrl.Replace(signedUri.Host, ip);
using (var httpClient = new HttpClient())
{
var request = new HttpRequestMessage(HttpMethod.Get, ipUrl);
request.Headers.Host = signedUri.Host; // Host头保持原域名
var response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
byte[] fileData = await response.Content.ReadAsByteArrayAsync();
string localDir = Path.GetDirectoryName(localPath);
if (!Directory.Exists(localDir))
{
Directory.CreateDirectory(localDir);
}
File.WriteAllBytes(localPath, fileData);
return true;
}
}
catch (Exception ex)
{
UpdateStatus($"备用方案用IP下载失败");
}
}
return false;
}
}
}