From 87d92672857ec0119a2b80212f9c43d2a1ab25d0 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Mon, 12 Jan 2026 23:45:32 +0800 Subject: [PATCH] :bug: Fix issues cause by new data structure between services of drive --- DysonNetwork.Drive/Storage/FileServiceGrpc.cs | 5 +- DysonNetwork.Shared/Models/CloudFile.cs | 25 ++++++- .../Models/CloudFileReferenceObject.cs | 68 ++++++++++++++++++- DysonNetwork.Shared/Proto/file.proto | 28 ++++++++ 4 files changed, 118 insertions(+), 8 deletions(-) diff --git a/DysonNetwork.Drive/Storage/FileServiceGrpc.cs b/DysonNetwork.Drive/Storage/FileServiceGrpc.cs index 2a8c4c03..01a1849d 100644 --- a/DysonNetwork.Drive/Storage/FileServiceGrpc.cs +++ b/DysonNetwork.Drive/Storage/FileServiceGrpc.cs @@ -1,4 +1,3 @@ -using DysonNetwork.Shared.Models; using DysonNetwork.Shared.Proto; using Google.Protobuf.WellKnownTypes; using Grpc.Core; @@ -7,7 +6,7 @@ namespace DysonNetwork.Drive.Storage { public class FileServiceGrpc(FileService fileService) : Shared.Proto.FileService.FileServiceBase { - public override async Task GetFile(GetFileRequest request, ServerCallContext context) + public override async Task GetFile(GetFileRequest request, ServerCallContext context) { var file = await fileService.GetFileAsync(request.Id); return file?.ToProtoValue() ?? throw new RpcException(new Status(StatusCode.NotFound, "File not found")); @@ -19,7 +18,7 @@ namespace DysonNetwork.Drive.Storage return new GetFileBatchResponse { Files = { files.Select(f => f.ToProtoValue()) } }; } - public override async Task UpdateFile(UpdateFileRequest request, + public override async Task UpdateFile(UpdateFileRequest request, ServerCallContext context) { var file = await fileService.GetFileAsync(request.File.Id); diff --git a/DysonNetwork.Shared/Models/CloudFile.cs b/DysonNetwork.Shared/Models/CloudFile.cs index 3f537062..437e0436 100644 --- a/DysonNetwork.Shared/Models/CloudFile.cs +++ b/DysonNetwork.Shared/Models/CloudFile.cs @@ -73,7 +73,7 @@ public class SnCloudFile : ModelBase, ICloudFile, IIdentifiedResource DeletedAt = DeletedAt, Id = Id, Name = Name, - FileMeta = FileMeta ?? [], + FileMeta = FileMeta, UserMeta = UserMeta ?? [], SensitiveMarks = SensitiveMarks, MimeType = MimeType, @@ -102,13 +102,32 @@ public class SnCloudFile : ModelBase, ICloudFile, IIdentifiedResource Url = StorageUrl ?? string.Empty, ContentType = MimeType ?? string.Empty, UploadedAt = UploadedAt?.ToTimestamp(), - // Convert file metadata FileMeta = GrpcTypeHelper.ConvertObjectToByteString(FileMeta), - // Convert user metadata UserMeta = GrpcTypeHelper.ConvertObjectToByteString(UserMeta), SensitiveMarks = GrpcTypeHelper.ConvertObjectToByteString(SensitiveMarks) }; + if (FileMeta.TryGetValue("width", out var width) && width is int w) + proto.Width = w; + if (FileMeta.TryGetValue("height", out var height) && height is int h) + proto.Height = h; + if (FileMeta.TryGetValue("blurhash", out var blurhash) && blurhash is string bh && !string.IsNullOrEmpty(bh)) + proto.Blurhash = bh; + + if (Object != null) + { + proto.Object = new Proto.FileObject + { + Id = Object.Id, + Size = Object.Size, + Meta = GrpcTypeHelper.ConvertObjectToByteString(Object.Meta), + MimeType = Object.MimeType ?? string.Empty, + Hash = Object.Hash ?? string.Empty, + HasCompression = Object.HasCompression, + HasThumbnail = Object.HasThumbnail + }; + } + return proto; } } \ No newline at end of file diff --git a/DysonNetwork.Shared/Models/CloudFileReferenceObject.cs b/DysonNetwork.Shared/Models/CloudFileReferenceObject.cs index cdeebbb2..4131a3e2 100644 --- a/DysonNetwork.Shared/Models/CloudFileReferenceObject.cs +++ b/DysonNetwork.Shared/Models/CloudFileReferenceObject.cs @@ -1,4 +1,5 @@ using System.ComponentModel.DataAnnotations; +using System.Text.Json; using DysonNetwork.Shared.Proto; namespace DysonNetwork.Shared.Models; @@ -44,12 +45,16 @@ public class SnCloudFileReferenceObject : ModelBase, ICloudFile public static SnCloudFileReferenceObject FromProtoValue(Proto.CloudFile proto) { + var fileMeta = proto.Object != null + ? ConvertObjectToDictionary(proto.Object.Meta) + : ConvertToDictionary(proto.FileMeta); + return new SnCloudFileReferenceObject { Id = proto.Id, Name = proto.Name, - FileMeta = GrpcTypeHelper.ConvertByteStringToObject>(proto.FileMeta) ?? [], - UserMeta = GrpcTypeHelper.ConvertByteStringToObject>(proto.UserMeta) ?? [], + FileMeta = fileMeta, + UserMeta = ConvertToDictionary(proto.UserMeta), SensitiveMarks = proto.HasSensitiveMarks ? GrpcTypeHelper.ConvertByteStringToObject>(proto.SensitiveMarks) : [], @@ -64,6 +69,65 @@ public class SnCloudFileReferenceObject : ModelBase, ICloudFile }; } + private static Dictionary ConvertObjectToDictionary(Google.Protobuf.ByteString byteString) + { + if (byteString.IsEmpty) + return []; + + var jsonElement = GrpcTypeHelper.ConvertByteStringToObject(byteString); + if (jsonElement.ValueKind != JsonValueKind.Object) + return []; + + var result = new Dictionary(); + foreach (var property in jsonElement.EnumerateObject()) + { + result[property.Name] = ConvertJsonElement(property.Value); + } + return result; + } + + private static Dictionary ConvertToDictionary(Google.Protobuf.ByteString byteString) + { + if (byteString.IsEmpty) + return []; + + var jsonElement = GrpcTypeHelper.ConvertByteStringToObject(byteString); + if (jsonElement.ValueKind != JsonValueKind.Object) + return []; + + var result = new Dictionary(); + foreach (var property in jsonElement.EnumerateObject()) + { + result[property.Name] = ConvertJsonElement(property.Value); + } + return result; + } + + private static object? ConvertJsonElement(JsonElement element) + { + return element.ValueKind switch + { + JsonValueKind.String => element.GetString(), + JsonValueKind.Number => element.TryGetInt64(out long l) ? l : element.GetDouble(), + JsonValueKind.True => true, + JsonValueKind.False => false, + JsonValueKind.Null => null, + JsonValueKind.Object => ConvertToDictionaryElement(element), + JsonValueKind.Array => element.EnumerateArray().Select(ConvertJsonElement).ToList(), + _ => null + }; + } + + private static Dictionary ConvertToDictionaryElement(JsonElement element) + { + var result = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + result[property.Name] = ConvertJsonElement(property.Value); + } + return result; + } + /// /// Converts the current object to its protobuf representation /// diff --git a/DysonNetwork.Shared/Proto/file.proto b/DysonNetwork.Shared/Proto/file.proto index 381c919b..58820c42 100644 --- a/DysonNetwork.Shared/Proto/file.proto +++ b/DysonNetwork.Shared/Proto/file.proto @@ -54,6 +54,34 @@ message CloudFile { // Blurhash for placeholder (optional, for images) optional string blurhash = 15; + + // Nested file object containing additional metadata + optional FileObject object = 16; +} + +// FileObject represents the actual file data stored in cloud storage. +// It contains metadata about the file content that may be shared across multiple references. +message FileObject { + // Unique identifier for the file object + string id = 1; + + // File size in bytes + int64 size = 2; + + // File metadata (e.g., dimensions, duration, etc.) stored as JSON bytes + bytes meta = 3; + + // MIME type of the file + string mime_type = 4; + + // File content hash (e.g., MD5, SHA-256) + string hash = 5; + + // Indicates if the file is stored with compression + bool has_compression = 6; + + // Indicates if the file has a thumbnail + bool has_thumbnail = 7; } // Service for file operations