Перейти к содержанию

Загрузка виртуального файла на клиенте без добавления его в карточку

Загрузка виртуального файла на клиенте без добавления его в карточку

Рассмотрим ситуацию, когда на клиенте при нажатии на кнопку или плитку требуется загрузить виртуальный или физический файл, который не приложен к текущей карточке, причём файл может иметь отношение к другой карточке с заданным идентификатором.

Файл должен быть загружен во временную папку, из которой он будет удалён только при обновлении или закрытии текущей карточки.

Для этого напишем вспомогательный метод, который асинхронно загружает файл с заданными параметрами и возвращает путь ко временному файлу или null, если файл загрузить не удалось.

using System; using System.IO; using System.Threading; using System.Threading.Tasks; using Tessa.Cards; using Tessa.Files; using Tessa.Platform.Validation; using Tessa.UI; using Tessa.UI.Cards;

namespace Tessa.Extensions.Client { public static class FileExtensionHelper { public static async Task<string> TryLoadVirtualFileAsync( ICardFileManager cardFileManager, ICardModel cardModel, string fileName, Guid cardID, Guid cardTypeID, Guid fileID, Guid versionID, CancellationToken cancellationToken = default) { // cardModel для файлового кэша, из которого временный файл попытается удалиться // после рефреша или закрытия вкладки с карточкой

// создаём псевдо-карточку с заданным идентификатором, и произвольными TypeName/TypeCaption var fakeCard = new Card { ID = cardID, TypeID = cardTypeID, TypeName = CardHelper.FileTypeName, TypeCaption = CardHelper.FileTypeCaption, };

// создаём псевдофайл ICardFileContainer container = await cardFileManager.CreateContainerAsync(fakeCard, cancellationToken: cancellationToken);

(IFile file, ValidationResult buildResult) = await container.FileContainer .BuildFile(fileName) .SetFileToken((x, _) => { x.ID = fileID; return ValueTask.CompletedTask; }) .SetVersionToken((x, _) => { x.ID = versionID; return ValueTask.CompletedTask; }) .SetContent(Stream.Null) .ReturnAsync(cancellationToken);

TessaDialog.ShowNotEmpty(buildResult); if (!buildResult.IsSuccessful) { return null; }

// создаём временный файл, в который будет записан контент IFileContent tempContent = await cardModel.FileContainer.Source.Cache.AllocateAsync(fileName, cancellationToken: cancellationToken); if (!tempContent.IsLocal) { throw new InvalidOperationException("Content isn't local when allocating from cache."); }

string tempPath = tempContent.GetLocalFilePath();

// асинхронно загружаем содержимое файла и сохраняем его в tempPath; // при загрузке не будут учитываться токены KrToken var target = System.IO.File.Create(tempPath); IFileContentResponse loadResponse = await Task.Run(async () => { var request = new FileContentRequest(file.Versions.Last) { ProcessContentActionAsync = async (p, ct) => await p.CopyToAsync(target, ct) }; return await container.FileContainer.Source.GetContentAsync(request); }, cancellationToken);

TessaDialog.ShowNotEmpty(loadResponse.ValidationResult); return loadResponse.ValidationResult.IsSuccessful ? tempPath : null; } } }

Пример расширения в карточке “Автомобиль”, которое пытается загрузить файл с некоторыми заданными идентификаторами, и в случае успеха файл открывается вызовом Process.Start().

using System; using System.Threading.Tasks; using Tessa.Cards; using Tessa.UI; using Tessa.UI.Cards; using Tessa.UI.Cards.Controls; using Unity; using Unity.Lifetime;

namespace Tessa.Extensions.Client { public sealed class TestUIExtension : CardUIExtension { public TestUIExtension(ICardFileManager cardFileManager) { this.cardFileManager = cardFileManager; }

private readonly ICardFileManager cardFileManager;

public override async Task Initialized(ICardUIExtensionContext context) { ICardModel cardModel = context.Model;

if (cardModel.Controls.TryGet("Get1CButton", out var control)) { var button = (ButtonViewModel)control; button.CommandClosure.Execute = async p => { string tempPath;

using (TessaSplash.Create(TessaSplashMessage.OpeningFile)) { // загружаем здесь печатный лист согласования для некоторой карточки договора tempPath = await FileExtensionHelper.TryLoadVirtualFileAsync( cardFileManager, cardModel, "file.txt", cardID: new Guid("b6d11bb3-0a6e-4fb3-be59-0f4a01f996b5"), cardTypeID: new Guid("b6d11bb3-0a6e-4fb3-be59-0f4a01f996b5"), fileID: new Guid("b6d11bb3-0a6e-4fb3-be59-0f4a01f996b5"), versionID: new Guid("b6d11bb3-0a6e-4fb3-be59-0f4a01f996b5")); }

if (!string.IsNullOrEmpty(tempPath)) { System.Diagnostics.Process.Start(tempPath); } }; } } }

[Registrator] public sealed class TestUIRegistrator : RegistratorBase { public override void RegisterUnity() { this.UnityContainer .RegisterType<TestUIExtension>(new ContainerControlledLifetimeManager()) ; }

public override void RegisterExtensions(IExtensionContainer extensionContainer) { extensionContainer .RegisterExtension<ICardUIExtension, TestUIExtension>(x => x .WithOrder(ExtensionStage.AfterPlatform, 100) .WithUnity(this.UnityContainer) .WhenCardTypes("Car")) ; } } }

Back to top