Files
jobtrackingapp/JobTrackerApi/Services/AvatarStorage.cs
T
cesnimda 4cf26405f6
CI and Deploy / test (push) Failing after 1m6s
CI and Deploy / deploy (push) Has been skipped
feat: complete phase 3 career workspace
2026-07-30 22:19:13 +02:00

38 lines
1.7 KiB
C#

using System.Security.Cryptography;
using System.Text;
namespace JobTrackerApi.Services;
public static class AvatarStorage
{
private const string FilePrefix = "file:";
public static async Task<string> StoreAsync(string dataRoot, string userId, byte[] bytes, string contentType, CancellationToken cancellationToken)
{
var userKey = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(userId))).ToLowerInvariant();
var folder = Path.Combine(dataRoot, "Avatars", userKey);
Directory.CreateDirectory(folder);
var extension = contentType switch { "image/png" => ".png", "image/webp" => ".webp", _ => ".jpg" };
var path = Path.Combine(folder, "avatar" + extension);
foreach (var old in Directory.EnumerateFiles(folder, "avatar.*")) if (!string.Equals(old, path, StringComparison.OrdinalIgnoreCase)) File.Delete(old);
await File.WriteAllBytesAsync(path, bytes, cancellationToken);
return FilePrefix + path;
}
public static string? Resolve(string? value)
{
if (string.IsNullOrWhiteSpace(value) || !value.StartsWith(FilePrefix, StringComparison.Ordinal)) return value;
var path = value[FilePrefix.Length..];
if (!File.Exists(path)) return null;
var contentType = Path.GetExtension(path).ToLowerInvariant() switch { ".png" => "image/png", ".webp" => "image/webp", _ => "image/jpeg" };
return $"data:{contentType};base64,{Convert.ToBase64String(File.ReadAllBytes(path))}";
}
public static void Delete(string? value)
{
if (value?.StartsWith(FilePrefix, StringComparison.Ordinal) != true) return;
var path = value[FilePrefix.Length..];
if (File.Exists(path)) File.Delete(path);
}
}