VersionFlow/Assets/VersionFlow/Editor/CDNUploader.cs
2025-08-08 10:33:30 +08:00

237 lines
8.5 KiB
C#

using Aliyun.OSS;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using UnityEditor;
using VersionFlow.Runtime;
namespace VersionFlow.Editors
{
public class CDNUploader
{
private OssClient m_ossclient;
private string m_bucketName;
public bool PendingMode { get; private set; }
public string BucketName => m_bucketName;
public string UploadRoot { get; private set; }
/// <summary>
/// 初始化上传器
/// </summary>
/// <param name="bucketName"></param>
/// <param name="uploadPath"></param>
/// <param name="accessKeyId"></param>
/// <param name="accessKeySecret"></param>
/// <param name="endPoint"></param>
/// <param name="pendingMode"></param>
/// <returns></returns>
public static CDNUploader Init(string bucketName, string uploadPath, string accessKeyId, string accessKeySecret, string endPoint, bool pendingMode)
{
CDNUploader client = new CDNUploader();
client.m_bucketName = bucketName;
client.UploadRoot = uploadPath;
client.PendingMode = pendingMode;
//accessKeyId = "LTAI5tAvUTxzcs5DCyczqow2";
//accessKeySecret = "aycbkKvNUEhAJXtuNevBi2E5BD1OVj";
//endPoint = "oss-cn-chengdu.aliyuncs.com";
client.m_ossclient = new OssClient(endPoint, accessKeyId, accessKeySecret);
return client;
}
public bool CheckFileExist(string relativePath)
{
relativePath = relativePath.Replace('\\', '/').TrimStart('/');
string filePathInBucket = $"{UploadRoot}/{relativePath}";
return m_ossclient.DoesObjectExist(m_bucketName, filePathInBucket);
}
public void UploadPatches(string patchDirPath)
{
var allPatchFiles = Directory.EnumerateFiles(patchDirPath, "*", SearchOption.AllDirectories).ToArray();
int step = 0;
int maxStep = allPatchFiles.Length;
List<string> objToRefresh = new List<string>();
foreach (var filePath in allPatchFiles)
{
var relativePath =
filePath
.Substring(patchDirPath.Length, filePath.Length - patchDirPath.Length)
.Replace("\\", "/").TrimStart('/');
string filePathInBucket = $"{UploadRoot}/{relativePath}";
if (PendingMode) filePathInBucket = $"PendingPatch_ORG/{filePathInBucket}";
var fileSt = new MemoryStream(File.ReadAllBytes(filePath));
EditorUtility.DisplayProgressBar($"上传文件", $"[{relativePath}] -> [{filePathInBucket}]", step * 1f / maxStep);
ObjectMetadata metadata = new ObjectMetadata() { ContentEncoding = "identity" };
m_ossclient.PutObject(m_bucketName, filePathInBucket, fileSt, metadata);
objToRefresh.Add(filePathInBucket);
step++;
}
if (!PendingMode)
{
var builder = AssetDatabase.LoadAssetAtPath<BuilderConfig>("Assets/Scripts/VersionFlow/Builder/Builder.asset");
builder.CDNRefresh(objToRefresh);
}
EditorUtility.ClearProgressBar();
}
public PutObjectResult UploadFile(string filePath, string appendHash)
{
string filePathInBucket = null;
var fileSt = new MemoryStream(File.ReadAllBytes(filePath));
if (appendHash != null)
{
var ext = Path.GetExtension(filePath);
var fileName = Path.GetFileNameWithoutExtension(filePath);
filePathInBucket = $"{UploadRoot}/{fileName}.{appendHash}{ext}";
}
else
{
var fileName = Path.GetFileName(filePath);
filePathInBucket = $"{UploadRoot}/{fileName}";
}
if (PendingMode) filePathInBucket = $"PendingPatch_ORG/{filePathInBucket}";
ObjectMetadata metadata = new ObjectMetadata() { ContentEncoding = "identity" };
var result = m_ossclient.PutObject(m_bucketName, filePathInBucket, fileSt, metadata);
return result;
}
public void DeleteFile(string fileName)
{
var filePathInBucket = $"{UploadRoot}/{fileName}";
m_ossclient.DeleteObject(m_bucketName, filePathInBucket);
}
public PutObjectResult UploadFile(string fileName, Stream fileSt)
{
var filePathInBucket = $"{UploadRoot}/{fileName}";
if (PendingMode) filePathInBucket = $"PendingPatch_ORG/{filePathInBucket}";
ObjectMetadata metadata = new ObjectMetadata() { ContentEncoding = "identity" };
var result = m_ossclient.PutObject(m_bucketName, filePathInBucket, fileSt, metadata);
return result;
}
public void UploadFileAsync(string fileName, Stream fileSt, Action<bool> callback)
{
var filePathInBucket = $"{UploadRoot}/{fileName}";
if (PendingMode) filePathInBucket = $"PendingPatch_ORG/{filePathInBucket}";
ObjectMetadata metadata = new ObjectMetadata() { ContentEncoding = "identity" };
PutObjectRequest putObjectRequest = new PutObjectRequest(m_bucketName, filePathInBucket, fileSt, metadata);
int? taskID = Progress.Start($"上传 \"{fileName}\"", fileName, Progress.Options.None);
putObjectRequest.StreamTransferProgress += ReportPorgress;
var task = Task.Run(() =>
{
try
{
var result = m_ossclient.PutObject(putObjectRequest);
EditorApplication.delayCall += () =>
{
Progress.Finish(taskID.Value);
taskID = null;
callback?.Invoke(true);
};
}
catch
{
EditorApplication.delayCall += () =>
{
if (taskID.HasValue)
{
Progress.Finish(taskID.Value, Progress.Status.Failed);
}
callback?.Invoke(false);
};
}
});
Progress.RegisterCancelCallback(taskID.Value, CancelProgress);
bool CancelProgress()
{
fileSt.Dispose();
Progress.Finish(taskID.Value, Progress.Status.Canceled);
taskID = null;
return true;
}
void ReportPorgress(object sender, StreamTransferProgressArgs args)
{
EditorApplication.delayCall += () =>
{
if (taskID.HasValue)
{
Progress.Report(taskID.Value, args.TransferredBytes * 1f / args.TotalBytes);
Progress.SetDescription(taskID.Value, $"{GetByteSizeString((ulong)args.TransferredBytes)}/{GetByteSizeString((ulong)args.TotalBytes)}");
}
};
}
}
private static string GetByteSizeString(ulong byteCount)
{
if (byteCount < 1024) return $"{byteCount}B";
if (byteCount < 1024 * 1024) return $"{byteCount / (1024f):.00}KB";
else return $"{byteCount / (1024f * 1024):.00}MB";
}
public byte[] DownloadFile(string file)
{
if (!CheckFileExist(file)) return null;
var fileObj = m_ossclient.GetObject(m_bucketName, $"{UploadRoot}/{file}");
if (fileObj == null) return null;
byte[] buffer = new byte[fileObj.ContentLength];
int readed = 0;
while (readed < buffer.Length - 1)
{
int read = fileObj.Content.Read(buffer, readed, buffer.Length - readed);
readed += read;
}
return buffer;
}
public void RefreshBundleManifestURL()
{
if (PendingMode) UploadRoot = $"PendingPatch_ORG/{UploadRoot}";
var builder = AssetDatabase.LoadAssetAtPath<BuilderConfig>("Assets/Scripts/VersionFlow/Builder/Builder.asset");
List<string> url = new List<string>()
{
$"{UploadRoot}/PatchManifest.json"
};
if (!PendingMode) builder.CDNRefresh(url);
}
}
}