/// <summary> /// Deletes this file or folder in the remote storage. /// </summary> public async Task DeleteAsync() { FileSystemInfo remoteStorageItem = FsPath.GetFileSystemItem(RemoteStoragePath); if (remoteStorageItem != null) { try { // Disable RemoteStorageMonitor to avoid circular calls. // This is only required because of the specifics of the simplicity of this example. Program.RemoteStorageMonitorInstance.Enabled = false; if (remoteStorageItem is FileInfo) { remoteStorageItem.Delete(); } else { (remoteStorageItem as DirectoryInfo).Delete(true); } } finally { Program.RemoteStorageMonitorInstance.Enabled = true; } } }
/// <summary> /// Called when a file content changed or file/folder attributes changed in the remote storage. /// </summary> /// <remarks> /// In this method we update corresponding file/folder information in user file system. /// We also dehydrate the file if it is not blocked. /// </remarks> private async void ChangedAsync(object sender, FileSystemEventArgs e) { LogMessage(e.ChangeType.ToString(), e.FullPath); string remoteStoragePath = e.FullPath; try { // We do not want to sync MS Office temp files, etc. from remote storage. if (!FsPath.AvoidSync(remoteStoragePath)) { string userFileSystemPath = Mapping.ReverseMapPath(remoteStoragePath); // Because of the on-demand population the file or folder placeholder may not exist in the user file system. if (FsPath.Exists(userFileSystemPath)) { FileSystemInfo remoteStorageItem = FsPath.GetFileSystemItem(remoteStoragePath); // This check is only required because we can not prevent circular calls because of the simplicity of this example. // In your real-life application you will not sent updates from server back to client that issued the update. FileSystemItemMetadataExt itemInfo = Mapping.GetUserFileSysteItemMetadata(remoteStorageItem); if (!await virtualDrive.GetETagManager(userFileSystemPath, this).ETagEqualsAsync(itemInfo)) { await virtualDrive.ServerNotifications(userFileSystemPath, this).UpdateAsync(itemInfo); LogMessage("Updated succesefully", userFileSystemPath); } } } } catch (Exception ex) { LogError($"{e.ChangeType} failed", remoteStoragePath, null, ex); } }
/// <summary> /// Renames or moves file or folder to a new location in the remote storage. /// </summary> /// <param name="userFileSystemNewPath">Target path of this file of folder in the user file system.</param> public async Task MoveToAsync(string userFileSystemNewPath) { string remoteStorageOldPath = RemoteStoragePath; string remoteStorageNewPath = Mapping.MapPath(userFileSystemNewPath); FileSystemInfo remoteStorageOldItem = FsPath.GetFileSystemItem(remoteStorageOldPath); if (remoteStorageOldItem != null) { try { // Disable RemoteStorageMonitor to avoid circular calls. // This is only required because of the specifics of the simplicity of this example. Program.RemoteStorageMonitorInstance.Enabled = false; if (remoteStorageOldItem is FileInfo) { (remoteStorageOldItem as FileInfo).MoveTo(remoteStorageNewPath, true); } else { (remoteStorageOldItem as DirectoryInfo).MoveTo(remoteStorageNewPath); } } finally { Program.RemoteStorageMonitorInstance.Enabled = true; } } }
/// <summary> /// Called when a file or folder is created in the remote storage. /// </summary> /// <remarks>In this method we create a new file/folder in the user file system.</remarks> private async void CreatedAsync(object sender, FileSystemEventArgs e) { LogMessage(e.ChangeType.ToString(), e.FullPath); string remoteStoragePath = e.FullPath; try { string userFileSystemPath = Mapping.ReverseMapPath(remoteStoragePath); // This check is only required because we can not prevent circular calls because of the simplicity of this example. // In your real-life application you will not sent updates from server back to client that issued the update. if (!FsPath.Exists(userFileSystemPath)) { string userFileSystemParentPath = Path.GetDirectoryName(userFileSystemPath); FileSystemInfo remoteStorageItem = FsPath.GetFileSystemItem(remoteStoragePath); if (remoteStorageItem != null) { IFileSystemItemMetadata newItemInfo = Mapping.GetUserFileSysteItemMetadata(remoteStorageItem); if (await engine.ServerNotifications(userFileSystemParentPath).CreateAsync(new[] { newItemInfo }) > 0) { // Because of the on-demand population, the parent folder placeholder may not exist in the user file system // or the folder may be offline. In this case the IServerNotifications.CreateAsync() call is ignored. LogMessage($"Created succesefully", userFileSystemPath); } } } } catch (Exception ex) { LogError($"{e.ChangeType} failed", remoteStoragePath, null, ex); } }
/// <summary> /// Called when a file or folder is created in the remote storage. /// </summary> /// <remarks>In this method we create a new file/folder in user file system.</remarks> private async void CreatedAsync(object sender, FileSystemEventArgs e) { LogMessage(e.ChangeType.ToString(), e.FullPath); string remoteStoragePath = e.FullPath; try { // We do not want to sync MS Office temp files from remote storage. if (!FsPath.AvoidSync(remoteStoragePath)) { string userFileSystemPath = Mapping.ReverseMapPath(remoteStoragePath); string userFileSystemParentPath = Path.GetDirectoryName(userFileSystemPath); // Because of the on-demand population the file or folder placeholder may not exist in the user file system // or the folder may be offline. FileSystemInfo remoteStorageItem = FsPath.GetFileSystemItem(remoteStoragePath); FileSystemItemMetadataExt newItemInfo = Mapping.GetUserFileSysteItemMetadata(remoteStorageItem); if (await virtualDrive.ServerNotifications(userFileSystemParentPath, this).CreateAsync(new[] { newItemInfo }) > 0) { LogMessage($"Created succesefully", userFileSystemPath); } } } catch (Exception ex) { LogError($"{e.ChangeType} failed", remoteStoragePath, null, ex); } }
/// <summary> /// Called when a file content changed or file/folder attributes changed in the remote storage. /// </summary> /// <remarks> /// In this method we update corresponding file/folder information in user file system. /// We also dehydrate the file if it is not blocked. /// </remarks> private async void ChangedAsync(object sender, FileSystemEventArgs e) { LogMessage(e.ChangeType.ToString(), e.FullPath); string remoteStoragePath = e.FullPath; string userFileSystemPath = null; try { userFileSystemPath = Mapping.ReverseMapPath(remoteStoragePath); // This check is only required because we can not prevent circular calls because of the simplicity of this example. // In your real-life application you will not sent updates from server back to client that issued the update. if (IsModified(userFileSystemPath, remoteStoragePath)) { FileSystemInfo remoteStorageItem = FsPath.GetFileSystemItem(remoteStoragePath); IFileSystemItemMetadata itemInfo = Mapping.GetUserFileSysteItemMetadata(remoteStorageItem); if (await engine.ServerNotifications(userFileSystemPath).UpdateAsync(itemInfo)) { // Because of the on-demand population the file or folder placeholder may not exist in the user file system. // In this case the IServerNotifications.UpdateAsync() call is ignored. LogMessage("Updated succesefully", userFileSystemPath); } } } catch (IOException ex) { // The file is blocked in the user file system. This is a normal behaviour. LogMessage(ex.Message); } catch (Exception ex) { LogError($"{e.ChangeType} failed", remoteStoragePath, null, ex); } }
///<inheritdoc> public async Task MoveToAsync(string userFileSystemNewPath, byte[] newParentItemId, IOperationContext operationContext, IConfirmationResultContext resultContext) { string userFileSystemOldPath = this.UserFileSystemPath; Logger.LogMessage($"{nameof(IFileSystemItem)}.{nameof(MoveToAsync)}()", userFileSystemOldPath, userFileSystemNewPath); string remoteStorageOldPath = RemoteStoragePath; string remoteStorageNewParentPath = WindowsFileSystemItem.GetPathByItemId(newParentItemId); string remoteStorageNewPath = Path.Combine(remoteStorageNewParentPath, Path.GetFileName(userFileSystemNewPath)); FileSystemInfo remoteStorageOldItem = FsPath.GetFileSystemItem(remoteStorageOldPath); if (remoteStorageOldItem != null) { if (remoteStorageOldItem is FileInfo) { (remoteStorageOldItem as FileInfo).MoveTo(remoteStorageNewPath, true); } else { (remoteStorageOldItem as DirectoryInfo).MoveTo(remoteStorageNewPath); } Logger.LogMessage("Moved item in remote storage succesefully", userFileSystemOldPath, userFileSystemNewPath); } }
///<inheritdoc> public async Task MoveToAsync(string userFileSystemNewPath, IOperationContext operationContext, IConfirmationResultContext resultContext) { // Here we will simply move the file in remote storage and confirm the operation. // In your implementation you may implement a more complex scenario with offline operations support. LogMessage("IFileSystemItem.MoveToAsync()", this.FullPath, userFileSystemNewPath); string userFileSystemOldPath = this.FullPath; try { bool?inSync = null; try { Program.RemoteStorageMonitorInstance.Enabled = false; // Disable RemoteStorageMonitor to avoid circular calls. // When a file is deleted, it is moved to a Recycle Bin, that is why we check for recycle bin here. if (FsPath.Exists(userFileSystemOldPath) && !FsPath.IsRecycleBin(userFileSystemNewPath) && !FsPath.AvoidSync(userFileSystemOldPath) && !FsPath.AvoidSync(userFileSystemNewPath)) { inSync = PlaceholderItem.GetItem(userFileSystemOldPath).GetInSync(); string remoteStorageOldPath = Mapping.MapPath(userFileSystemOldPath); string remoteStorageNewPath = Mapping.MapPath(userFileSystemNewPath); FileSystemInfo remoteStorageOldItem = FsPath.GetFileSystemItem(remoteStorageOldPath); if (remoteStorageOldItem is FileInfo) { (remoteStorageOldItem as FileInfo).MoveTo(remoteStorageNewPath); } else { (remoteStorageOldItem as DirectoryInfo).MoveTo(remoteStorageNewPath); } LogMessage("Moved succesefully:", remoteStorageOldPath, remoteStorageNewPath); } } finally { resultContext.ReturnConfirmationResult(); // If a file with content is deleted it is moved to a recycle bin and converted // to a regular file, so placeholder features are not available on it. if ((inSync != null) && PlaceholderItem.IsPlaceholder(userFileSystemNewPath)) { PlaceholderItem.GetItem(userFileSystemNewPath).SetInSync(inSync.Value); } } } catch (Exception ex) { // remove try-catch when error processing inside CloudProvider is fixed. LogError("Move failed:", $"From: {this.FullPath} to:{userFileSystemNewPath}", ex); } finally { Program.RemoteStorageMonitorInstance.Enabled = true; } }
///<inheritdoc> public async Task DeleteAsync(IOperationContext operationContext, IConfirmationResultContext resultContext) { // Here we will simply delete the file in remote storage and confirm the operation. // In your implementation you may implement a more complex scenario with offline operations support. LogMessage("IFileSystemItem.DeleteAsync()", this.FullPath); string userFileSystemPath = this.FullPath; string remoteStoragePath = null; try { try { Program.RemoteStorageMonitorInstance.Enabled = false; // Disable RemoteStorageMonitor to avoid circular calls. remoteStoragePath = Mapping.MapPath(userFileSystemPath); if (FsPath.Exists(remoteStoragePath) && !FsPath.AvoidSync(userFileSystemPath)) { FileSystemInfo remoteStorageItem = FsPath.GetFileSystemItem(remoteStoragePath); remoteStorageItem.Delete(); LogMessage("Deleted succesefully:", remoteStoragePath); } } finally { resultContext.ReturnConfirmationResult(); } } catch (Exception ex) { // remove try-catch when error processing inside CloudProvider is fixed. LogError("Delete failed:", remoteStoragePath, ex); } finally { Program.RemoteStorageMonitorInstance.Enabled = true; } }
/// <inheritdoc/> public async Task DeleteCompletionAsync(IOperationContext operationContext, IResultContext resultContext) { // On Windows, for move with overwrite to function properly for folders, // the deletion of the folder in the remote storage must be done in DeleteCompletionAsync() // Otherwise the folder will be deleted before files in it can be moved. Logger.LogMessage($"{nameof(IFileSystemItem)}.{nameof(DeleteCompletionAsync)}()", this.UserFileSystemPath); FileSystemInfo remoteStorageItem = FsPath.GetFileSystemItem(RemoteStoragePath); if (remoteStorageItem != null) { if (remoteStorageItem is FileInfo) { remoteStorageItem.Delete(); } else { (remoteStorageItem as DirectoryInfo).Delete(true); } Logger.LogMessage("Deleted item in remote storage succesefully", UserFileSystemPath); } }