Learn.VideoAnalysis/VideoAnalysisCore/Common/DownloadFile.cs

157 lines
6.7 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using AntDesign;
using Downloader;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Threading.Tasks;
namespace VideoAnalysisCore.Common
{
/// <summary>
///
/// </summary>
public class DownloadFile
{
static DownloadConfiguration Opt { get; set; } = default!;
/// <summary>
/// 初始化下载器
/// </summary>
/// <param name="DownloadSpeed">下载速度mb/s 默认8</param>
static void Init(int DownloadSpeed = 8)
{
Opt = new DownloadConfiguration()
{
// 通常主机支持的最大值为8000字节默认值是8000
BufferBlockSize = 10240,
// 要下载的文件部分数量默认值是1
ChunkCount = 8,
// 下载速度限制为2MB/秒,默认值为零(即无限制)
MaximumBytesPerSecond = 1024 * 1024 * DownloadSpeed,
// 故障转移时的最大重试次数
MaxTryAgainOnFailover = 5,
// 每50MB后释放内存缓冲区
MaximumMemoryBufferBytes = 1024 * 1024 * 50,
// 是否并行下载文件的各个部分。默认值为false
ParallelDownload = true,
// 并行下载的数量。默认值与分块数量相同
ParallelCount = 4,
// 每个流块读取器的超时时间毫秒默认值是1000
Timeout = 1000,
// 如果只想下载大型文件的特定字节范围则设置为true
RangeDownload = false,
// 大型文件下载范围的起始偏移量
RangeLow = 0,
// 大型文件下载范围的结束偏移量
RangeHigh = 0,
// 下载失败完成时清除包块数据默认值为false
ClearPackageOnCompletionWithFailure = true,
// 将文件分多个部分下载时的最小分块大小默认值是512
MinimumSizeOfChunking = 1024,
// 在开始下载之前按照文件大小预留文件的存储空间默认值为false
ReserveStorageSpaceBeforeStartingDownload = true,
// 在下载进度改变事件中通过ReceivedBytes获取按需下载的数据
EnableLiveStreaming = false,
// 配置和自定义请求头
RequestConfiguration =
{
Accept = "*/*",
//CookieContainer = cookies,
Headers = new WebHeaderCollection(), // { 你的自定义头部信息 }
KeepAlive = true, // 默认值为false
ProtocolVersion = HttpVersion.Version11, // 默认值是HTTP 1.1
UseDefaultCredentials = false,
// 你的自定义用户代理或你的应用名称/应用版本。
UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
//Proxy = new WebProxy()//使用代理
//{
// Address = new Uri("http://Learn.VideoAnalysis"),
// UseDefaultCredentials = false,
// Credentials = System.Net.CredentialCache.DefaultNetworkCredentials,
// BypassProxyOnLocal = true
//}
}
};
}
// 根据 Content-Type 映射文件后缀
static string GetExtensionFromContentType(HttpResponseMessage res)
{
var contentType = res.Content.Headers.ContentType?.MediaType;
return contentType switch
{
"application/pdf" => ".pdf",
"image/jpeg" => ".jpg",
"image/png" => ".png",
"application/zip" => ".zip",
"text/html" => ".html",
"audio/wav" => ".wav",
"audio/mp4" => ".mp4",
"audio/mp3" => ".mp3",
// 根据需要添加其他 Content-Type 映射
_ => ".mp4", // 默认二进制文件
};
}
/// <summary>
/// 使用 HttpClient 下载任务的资源文件到本地
/// </summary>
/// <param name="task"></param>
/// <returns></returns>
public static async Task RunTask(string task)
{
if (Opt is null)
Init();
//获取资源文件 地址
var fileUrl = RedisExpand.Redis.HMGet(RedisExpandKey.Task(task), "MediaUrl")
.FirstOrDefault();
if (string.IsNullOrEmpty(fileUrl))
throw new Exception($"任务id[{task}] 资源地址无效 {fileUrl}");
// 尝试从 URL 中获取文件后缀
string fileExtension = Path.GetExtension(new Uri(fileUrl).AbsolutePath);
//否则 获取 从Content-Type 获取文件后缀
if (string.IsNullOrEmpty(fileExtension))
throw new Exception($"未能从资源路径中获取文件后缀");
//创建下载文件缓存路径
if (!Directory.Exists(AppCommon.TaskCachedFile)) Directory.CreateDirectory(AppCommon.TaskCachedFile);
var localPath = task.LocalPath();
var outputPath = Path.Combine(localPath, task + fileExtension);
if (!Directory.Exists(localPath)) Directory.CreateDirectory(localPath);
RedisExpand.Redis.HSet(RedisExpandKey.Task(task), "LocalMediaPath", outputPath);
IDownload download = DownloadBuilder.New()
.WithUrl(fileUrl)
.WithDirectory(localPath)
.WithFileName(task + fileExtension)
.WithConfiguration(Opt)
.Build();
download.DownloadProgressChanged += (object? sender, Downloader.DownloadProgressChangedEventArgs e) =>
{
RedisExpand.SetTaskProgress(task, e.ProgressPercentage);
};
download.DownloadFileCompleted +=async (object? sender, AsyncCompletedEventArgs e) =>
{
if (download.Status == DownloadStatus.Failed && e.Error!=null)
{
await RedisExpand.SetTaskErrorMessage(long.Parse(task), e.Error)
.ConfigureAwait(false);//不切回上下文
return;
}
else if (download.Status == DownloadStatus.Completed)
{
//加入下一队列
RedisExpand.InsertChannel(Enum.RedisChannelEnum.SeparateAudio, task);
return;
}
};
await download.StartAsync();
}
}
}