using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.Core; using Tango.Core.DI; using Tango.Core.IO; using Tango.FileSystem; using Tango.FileSystem.Network; using Tango.Integration.ExternalBridge; using Tango.PPC.Common.ExternalBridge; using Tango.Transport; namespace Tango.PPC.Common.FileSystem { [TangoCreateWhenRegistered] public class DefaultFileSystemService : ExtendedObject, IFileSystemService, IExternalBridgeRequestHandler { private enum FileSystemOperationMode { Upload, Download } private class FileSystemOperation { public FileSystemOperationMode Mode { get; set; } public String Id { get; set; } public String Path { get; set; } public bool IsPathTempZip { get; set; } public FileSystemOperation(FileSystemOperationMode mode, String path) { Mode = mode; Id = Guid.NewGuid().ToString(); Path = path; } } private FileSystemManager _manager; private Dictionary _operations; public bool Enabled { get; set; } = true; public DefaultFileSystemService(IPPCExternalBridgeService externalBridge) { _manager = new FileSystemManager(); _operations = new Dictionary(); externalBridge.RegisterRequestHandler(this); } [ExternalBridgeRequestHandlerMethod(typeof(GetFileSystemItemRequest))] public async void OnGetFileSystemItemRequest(GetFileSystemItemRequest request, String token, ExternalBridgeReceiver receiver) { try { FileSystemItemDTO dto = _manager.GetFolder(request); await receiver.SendGenericResponse(new GetFileSystemItemResponse() { FileSystemItem = dto }, token); } catch (Exception ex) { await receiver.SendErrorResponse(ex, token); } } [ExternalBridgeRequestHandlerMethod(typeof(FileUploadRequest))] public async void OnFileUploadRequest(FileUploadRequest request, String token, ExternalBridgeReceiver receiver) { try { using (var stream = new FileStream(request.Path, FileMode.Create)) { } FileSystemOperation operation = new FileSystemOperation(FileSystemOperationMode.Upload, request.Path); _operations.Add(operation.Id, operation); await receiver.SendGenericResponse(new FileUploadResponse() { OperationId = operation.Id }, token); } catch (Exception ex) { await receiver.SendErrorResponse(ex, token); } } [ExternalBridgeRequestHandlerMethod(typeof(FileDownloadRequest))] public async void OnFileDownloadRequest(FileDownloadRequest request, String token, ExternalBridgeReceiver receiver) { try { if (!File.Exists(request.Path)) { await receiver.SendErrorResponse(new FileNotFoundException("Could not find the specified file."), token); return; } FileSystemOperation operation = new FileSystemOperation(FileSystemOperationMode.Download, request.Path); _operations.Add(operation.Id, operation); await receiver.SendGenericResponse(new FileDownloadResponse() { OperationId = operation.Id, Length = new FileInfo(request.Path).Length }, token); } catch (Exception ex) { await receiver.SendErrorResponse(ex, token); } } [ExternalBridgeRequestHandlerMethod(typeof(FolderDownloadRequest))] public async void OnFolderDownloadRequest(FolderDownloadRequest request, String token, ExternalBridgeReceiver receiver) { try { if (!Directory.Exists(request.Path)) { await receiver.SendErrorResponse(new FileNotFoundException("Could not find the specified directory."), token); return; } var tempFile = TemporaryManager.CreateImaginaryFile(); ZipFile.CreateFromDirectory(request.Path, tempFile); FileSystemOperation operation = new FileSystemOperation(FileSystemOperationMode.Download, tempFile); operation.IsPathTempZip = true; _operations.Add(operation.Id, operation); await receiver.SendGenericResponse(new FileDownloadResponse() { OperationId = operation.Id, Length = new FileInfo(request.Path).Length }, token); } catch (Exception ex) { await receiver.SendErrorResponse(ex, token); } } [ExternalBridgeRequestHandlerMethod(typeof(ChunkUploadRequest))] public async void OnChunkUploadRequest(ChunkUploadRequest request, String token, ExternalBridgeReceiver receiver) { try { FileSystemOperation operation; _operations.TryGetValue(request.OperationId, out operation); if (operation == null) { await receiver.SendErrorResponse(new ArgumentException("Invalid operation id."), token); return; } using (var stream = new FileStream(operation.Path, FileMode.Append)) { stream.Write(request.Data, 0, request.Data.Length); } await receiver.SendGenericResponse(new ChunkUploadResponse(), token); } catch (Exception ex) { await receiver.SendErrorResponse(ex, token); } } [ExternalBridgeRequestHandlerMethod(typeof(ChunkDownloadRequest))] public async void OnChunkDownloadRequest(ChunkDownloadRequest request, String token, ExternalBridgeReceiver receiver) { FileSystemOperation operation; _operations.TryGetValue(request.OperationId, out operation); if (operation == null) { await receiver.SendErrorResponse(new ArgumentException("Invalid operation id."), token); return; } using (FileStream stream = new FileStream(operation.Path, FileMode.Open)) { stream.Position = request.Position; byte[] data = new byte[Math.Min(request.MaxChunkSize, stream.Length - stream.Position)]; await stream.ReadAsync(data, 0, data.Length); await receiver.SendGenericResponse(new ChunkDownloadResponse() { Data = data }, token); } } [ExternalBridgeRequestHandlerMethod(typeof(AbortOperationRequest))] public async void OnAbortOperationRequest(AbortOperationRequest request, String token, ExternalBridgeReceiver receiver) { FileSystemOperation operation; _operations.TryGetValue(request.OperationId, out operation); if (operation == null) { await receiver.SendErrorResponse(new ArgumentException("Invalid operation id."), token); return; } try { if (operation.Mode == FileSystemOperationMode.Upload) { if (File.Exists(operation.Path)) { File.Delete(operation.Path); } else if (Directory.Exists(operation.Path)) { Directory.Delete(operation.Path, true); } } else if (operation.IsPathTempZip) { if (File.Exists(operation.Path)) { File.Delete(operation.Path); } } await receiver.SendGenericResponse(new AbortOperationResponse(), token); } catch (Exception ex) { await receiver.SendErrorResponse(ex, token); } } public void OnReceiverDisconnected(ExternalBridgeReceiver receiver) { } } }