mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-25 15:09:26 -07:00
55 lines
2.0 KiB
C#
55 lines
2.0 KiB
C#
using System.Numerics;
|
|
using System.Security.Cryptography;
|
|
|
|
namespace RadicadeServer.Storage;
|
|
|
|
public sealed record StudioAssetUpload(string Filename, string Hash, long Length);
|
|
|
|
public static class StudioAssetStorage
|
|
{
|
|
|
|
|
|
public static string Filename(byte[] digest)
|
|
{
|
|
var value = new BigInteger(digest, isUnsigned: true, isBigEndian: false);
|
|
const string alphabet = "0123456789abcdefghijklmnopqrstuvwxyz";
|
|
var result = "";
|
|
while (value > 0)
|
|
{
|
|
value = BigInteger.DivRem(value, 36, out var remainder);
|
|
result = alphabet[(int)remainder] + result;
|
|
}
|
|
return result.PadLeft(50, '0')[..40];
|
|
}
|
|
|
|
public static async Task<StudioAssetUpload> Save(IFormFile file, CancellationToken cancellation)
|
|
{
|
|
await using var input = file.OpenReadStream();
|
|
return await Save(input, cancellation);
|
|
}
|
|
|
|
public static async Task<StudioAssetUpload> Save(Stream input, CancellationToken cancellation)
|
|
{
|
|
Directory.CreateDirectory(DBConfig.CDNStorage);
|
|
var temporary = Path.Combine(DBConfig.CDNStorage, Guid.NewGuid() + ".uploading");
|
|
try
|
|
{
|
|
await using (var output = System.IO.File.Create(temporary))
|
|
await input.CopyToAsync(output, cancellation);
|
|
var length = new FileInfo(temporary).Length;
|
|
byte[] hash;
|
|
await using (var storedFile = System.IO.File.OpenRead(temporary))
|
|
hash = await SHA256.HashDataAsync(storedFile, cancellation);
|
|
var filename = Filename(hash);
|
|
var destination = Path.Combine(DBConfig.CDNStorage, filename);
|
|
try { System.IO.File.Move(temporary, destination); }
|
|
catch (IOException) when (System.IO.File.Exists(destination)) { }
|
|
return new StudioAssetUpload(filename, Convert.ToBase64String(hash), length);
|
|
}
|
|
finally
|
|
{
|
|
if (System.IO.File.Exists(temporary)) System.IO.File.Delete(temporary);
|
|
}
|
|
}
|
|
}
|