v2rayN/v2rayN/ServiceLib/Common/HttpClientHelper.cs

192 lines
6.5 KiB
C#
Raw Normal View History

using System.Net.Http.Headers;
2023-02-20 10:16:30 +00:00
using System.Net.Mime;
using System.Text;
2022-04-11 07:26:32 +00:00
2024-08-19 10:15:54 +00:00
namespace ServiceLib.Common
2022-04-11 07:26:32 +00:00
{
/// <summary>
/// </summary>
public class HttpClientHelper
{
2023-04-14 12:49:36 +00:00
private static readonly Lazy<HttpClientHelper> _instance = new(() =>
2022-04-11 07:26:32 +00:00
{
2024-12-06 06:01:11 +00:00
SocketsHttpHandler handler = new() { UseCookies = false };
2023-02-20 10:16:30 +00:00
HttpClientHelper helper = new(new HttpClient(handler));
return helper;
});
2023-04-14 12:49:36 +00:00
2023-02-20 10:16:30 +00:00
public static HttpClientHelper Instance => _instance.Value;
private readonly HttpClient httpClient;
private HttpClientHelper(HttpClient httpClient) => this.httpClient = httpClient;
2022-04-11 07:26:32 +00:00
public async Task<string?> TryGetAsync(string url)
{
2024-09-17 08:52:41 +00:00
if (Utils.IsNullOrEmpty(url))
return null;
try
{
2024-10-14 02:57:40 +00:00
var response = await httpClient.GetAsync(url);
return await response.Content.ReadAsStringAsync();
}
catch
{
return null;
}
}
2023-02-17 06:36:28 +00:00
public async Task<string?> GetAsync(string url)
2022-04-11 07:26:32 +00:00
{
2025-01-30 09:10:05 +00:00
if (Utils.IsNullOrEmpty(url))
return null;
2023-02-20 10:16:30 +00:00
return await httpClient.GetStringAsync(url);
2022-04-11 07:26:32 +00:00
}
2023-02-24 03:13:13 +00:00
2023-02-20 10:16:30 +00:00
public async Task<string?> GetAsync(HttpClient client, string url, CancellationToken token = default)
2022-04-11 07:26:32 +00:00
{
2025-01-30 09:10:05 +00:00
if (Utils.IsNullOrEmpty(url))
return null;
2023-02-20 10:16:30 +00:00
return await client.GetStringAsync(url, token);
2022-04-11 07:26:32 +00:00
}
public async Task PutAsync(string url, Dictionary<string, string> headers)
{
2024-03-26 06:26:03 +00:00
var jsonContent = JsonUtils.Serialize(headers);
2023-02-20 10:16:30 +00:00
var content = new StringContent(jsonContent, Encoding.UTF8, MediaTypeNames.Application.Json);
2022-04-11 07:26:32 +00:00
2023-02-20 10:16:30 +00:00
var result = await httpClient.PutAsync(url, content);
2022-04-11 07:26:32 +00:00
}
public async Task PatchAsync(string url, Dictionary<string, string> headers)
{
var myContent = JsonUtils.Serialize(headers);
var buffer = System.Text.Encoding.UTF8.GetBytes(myContent);
var byteContent = new ByteArrayContent(buffer);
byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
await httpClient.PatchAsync(url, byteContent);
}
public async Task DeleteAsync(string url)
{
await httpClient.DeleteAsync(url);
}
2023-02-20 10:16:30 +00:00
public static async Task DownloadFileAsync(HttpClient client, string url, string fileName, IProgress<double>? progress, CancellationToken token = default)
2022-04-11 07:26:32 +00:00
{
2023-02-20 10:16:30 +00:00
ArgumentNullException.ThrowIfNull(url);
ArgumentNullException.ThrowIfNull(fileName);
2025-01-30 09:10:05 +00:00
if (File.Exists(fileName))
File.Delete(fileName);
2022-04-11 07:26:32 +00:00
2023-02-20 10:16:30 +00:00
using var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
2022-04-11 07:26:32 +00:00
2025-01-30 09:10:05 +00:00
if (!response.IsSuccessStatusCode)
throw new Exception(response.StatusCode.ToString());
2022-04-11 07:26:32 +00:00
2023-02-19 05:34:22 +00:00
var total = response.Content.Headers.ContentLength ?? -1L;
2022-04-11 07:26:32 +00:00
var canReportProgress = total != -1 && progress != null;
2024-10-14 02:57:40 +00:00
await using var stream = await response.Content.ReadAsStreamAsync(token);
await using var file = File.Create(fileName);
2023-02-17 06:36:28 +00:00
var totalRead = 0L;
var buffer = new byte[1024 * 1024];
var progressPercentage = 0;
2023-02-20 10:16:30 +00:00
while (true)
2022-04-11 07:26:32 +00:00
{
2023-02-17 06:36:28 +00:00
token.ThrowIfCancellationRequested();
2023-02-19 05:34:22 +00:00
var read = await stream.ReadAsync(buffer, token);
2023-02-20 10:16:30 +00:00
totalRead += read;
2023-02-17 06:36:28 +00:00
2025-01-30 09:10:05 +00:00
if (read == 0)
break;
await file.WriteAsync(buffer.AsMemory(0, read), token);
2022-04-11 07:26:32 +00:00
2023-02-20 10:16:30 +00:00
if (canReportProgress)
{
var percent = (int)(100.0 * totalRead / total);
//if (progressPercentage != percent && percent % 10 == 0)
2022-04-11 07:26:32 +00:00
{
2023-02-20 10:16:30 +00:00
progressPercentage = percent;
2024-03-13 08:38:37 +00:00
progress?.Report(percent);
2022-04-11 07:26:32 +00:00
}
}
2023-02-20 10:16:30 +00:00
}
2023-02-17 06:36:28 +00:00
if (canReportProgress)
{
2024-03-13 08:38:37 +00:00
progress?.Report(101);
2022-04-11 07:26:32 +00:00
}
}
2023-02-20 10:16:30 +00:00
public async Task DownloadDataAsync4Speed(HttpClient client, string url, IProgress<string> progress, CancellationToken token = default)
2022-04-11 07:26:32 +00:00
{
2024-03-26 06:26:03 +00:00
if (Utils.IsNullOrEmpty(url))
2022-04-11 07:26:32 +00:00
{
2023-02-17 06:36:28 +00:00
throw new ArgumentNullException(nameof(url));
2022-04-11 07:26:32 +00:00
}
var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, token);
if (!response.IsSuccessStatusCode)
{
2023-02-20 10:16:30 +00:00
throw new Exception(response.StatusCode.ToString());
2022-04-11 07:26:32 +00:00
}
2022-04-25 11:07:09 +00:00
//var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L;
//var canReportProgress = total != -1 && progress != null;
2022-04-11 07:26:32 +00:00
2024-10-14 02:57:40 +00:00
await using var stream = await response.Content.ReadAsStreamAsync(token);
2023-02-17 06:36:28 +00:00
var totalRead = 0L;
var buffer = new byte[1024 * 64];
var isMoreToRead = true;
2024-10-14 02:57:40 +00:00
var progressSpeed = string.Empty;
var totalDatetime = DateTime.Now;
var totalSecond = 0;
2023-02-17 06:36:28 +00:00
do
2022-04-11 07:26:32 +00:00
{
2023-02-17 06:36:28 +00:00
if (token.IsCancellationRequested)
2022-04-11 07:26:32 +00:00
{
2023-02-17 06:36:28 +00:00
if (totalRead > 0)
2022-04-12 05:38:42 +00:00
{
2023-02-17 06:36:28 +00:00
return;
2022-04-11 07:26:32 +00:00
}
else
{
2023-02-17 06:36:28 +00:00
token.ThrowIfCancellationRequested();
}
}
2023-02-19 05:34:22 +00:00
var read = await stream.ReadAsync(buffer, token);
2022-04-11 07:26:32 +00:00
2023-02-17 06:36:28 +00:00
if (read == 0)
{
isMoreToRead = false;
}
else
{
var data = new byte[read];
buffer.ToList().CopyTo(0, data, 0, read);
2022-04-11 07:26:32 +00:00
2023-02-17 06:36:28 +00:00
totalRead += read;
2024-10-14 02:57:40 +00:00
var ts = (DateTime.Now - totalDatetime);
2023-02-17 06:36:28 +00:00
if (progress != null && ts.Seconds > totalSecond)
{
totalSecond = ts.Seconds;
var speed = (totalRead * 1d / ts.TotalMilliseconds / 1000).ToString("#0.0");
if (progressSpeed != speed)
2022-04-25 05:24:10 +00:00
{
2023-02-17 06:36:28 +00:00
progressSpeed = speed;
progress.Report(speed);
2022-04-25 05:24:10 +00:00
}
2022-04-11 07:26:32 +00:00
}
2023-02-17 06:36:28 +00:00
}
} while (isMoreToRead);
2022-04-11 07:26:32 +00:00
}
}
2025-01-30 09:10:05 +00:00
}