releases/VideoDownloader.Core/Util/FileNameUtil.cs

50 lines
2 KiB
C#

using System.Text;
namespace VideoDownloader.Core.Util;
public static class FileNameUtil
{
private static readonly char[] Invalid = Path.GetInvalidFileNameChars();
// 무의미한 제네릭 이름 (이름 추출 시 건너뜀)
private static readonly HashSet<string> GenericNames = new(StringComparer.OrdinalIgnoreCase)
{
"index", "playlist", "playlists", "master", "chunklist", "main", "play",
"media", "video", "stream", "streaming", "vod", "output", "file", "hls",
"dash", "manifest", "seg", "segment", "test", "default"
};
/// <summary>파일명으로 사용 불가능한 문자를 '_'로 치환하고 길이를 제한한다.</summary>
public static string Sanitize(string? name, int maxLen = 120)
{
if (string.IsNullOrWhiteSpace(name)) return "video";
var extra = new[] { '"', '<', '>', '|', '*', '?' };
var sb = new StringBuilder();
foreach (var c in name.Trim())
{
if (Array.IndexOf(Invalid, c) >= 0 || Array.IndexOf(extra, c) >= 0) sb.Append('_');
else sb.Append(c);
}
var result = sb.ToString().Trim().Trim('.');
if (string.IsNullOrWhiteSpace(result)) result = "video";
return result.Length > maxLen ? result[..maxLen].Trim() : result;
}
/// <summary>미디어 URL 에서 '진짜 파일명'을 추출 (페이지 타이틀 사용 X).</summary>
public static string DeriveName(Uri url)
{
var segs = url.Segments
.Select(s => Uri.UnescapeDataString(s).Trim('/'))
.Where(s => s.Length > 0)
.ToArray();
for (int i = segs.Length - 1; i >= 0; i--)
{
var withoutExt = Path.GetFileNameWithoutExtension(segs[i]);
if (string.IsNullOrWhiteSpace(withoutExt)) continue;
if (GenericNames.Contains(withoutExt)) continue; // index.m3u8 등은 건너뜀
return Sanitize(withoutExt);
}
return Sanitize(url.Host); // fallback: 호스트명
}
}