oss 无dns下载实现
This commit is contained in:
197
Form1.cs
197
Form1.cs
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user