/// <summary> /// Moves a file or folder placeholder in user file system. /// </summary> /// <param name="userFileSystemNewPath">New path in user file system.</param> /// <remarks> /// This method failes if the file or folder in user file system is modified (not in sync with the remote storage) /// or if the target file exists. /// </remarks> public async Task MoveToAsync(string userFileSystemNewPath) { // Cloud Filter API does not provide a function to move a placeholder file only if it is not modified. // The file may be modified between InSync call, Move() call and SetInSync() in this method. try { // Because of the on-demand population the file or folder placeholder may not exist in the user file system. if (FsPath.Exists(userFileSystemPath)) { bool inSync = PlaceholderItem.GetItem(userFileSystemPath).GetInSync(); if (inSync) { string eTag = await ETag.GetETagAsync(userFileSystemPath); ETag.DeleteETag(userFileSystemPath); try { Directory.Move(userFileSystemPath, userFileSystemNewPath); } catch { await ETag.SetETagAsync(userFileSystemPath, eTag); throw; } await ETag.SetETagAsync(userFileSystemNewPath, eTag); // The file is marked as not in sync after move/rename. Marking it as in-sync. PlaceholderItem placeholderItem = PlaceholderItem.GetItem(userFileSystemNewPath); placeholderItem.SetInSync(true); placeholderItem.SetOriginalPath(userFileSystemNewPath); await new UserFileSystemRawItem(userFileSystemNewPath).ClearStateAsync(); } if (!inSync) { throw new ConflictException(Modified.Client, "The item is not in-sync with the cloud."); } } } catch (Exception ex) { string path = FsPath.Exists(userFileSystemNewPath) ? userFileSystemNewPath : userFileSystemPath; await new UserFileSystemRawItem(userFileSystemPath).SetDownloadErrorStateAsync(ex); // Rethrow the exception preserving stack trace of the original exception. System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex).Throw(); } }
/// <summary> /// Creates or updates file in the remote storage. /// </summary> /// <param name="remoteStorageUri">Uri of the file to be created or updated in the remote storage.</param> /// <param name="newInfo">New information about the file, such as modification date, attributes, custom data, etc.</param> /// <param name="mode">Specifies if a new file should be created or existing file should be updated.</param> /// <param name="content">New file content or null if the file content is not modified.</param> /// <param name="lockInfo">Information about the lock. Caller passes null if the item is not locked.</param> /// <returns>New ETag returned from the remote storage.</returns> protected async Task <string> CreateOrUpdateFileAsync(Uri remoteStorageUri, IFileBasicInfo newInfo, FileMode mode, Stream content = null, ServerLockInfo lockInfo = null) { string eTag = null; string lockToken = null; // Get ETag and lock-token here and send it to the remote storage with the new item content/info. if (mode == FileMode.Open) { // Get ETag. eTag = await ETag.GetETagAsync(UserFileSystemPath); // Get lock-token. lockToken = lockInfo?.LockToken; } if (content != null || mode == FileMode.CreateNew) { long contentLength = content != null ? content.Length : 0; IWebRequestAsync request = await Program.DavClient.GetFileWriteRequestAsync(remoteStorageUri, null, contentLength, 0, -1, lockToken, eTag); // Update remote storage file content. using (Stream davContentStream = await request.GetRequestStreamAsync()) { if (content != null) { await content.CopyToAsync(davContentStream); } // Get ETag returned by the server, if any. IWebResponseAsync response = await request.GetResponseAsync(); eTag = response.Headers["ETag"]; response.Close(); } } return(eTag); }
internal async Task MoveToAsync(string userFileSystemNewPath, IConfirmationResultContext resultContext = null) { string userFileSystemOldPath = userFileSystemPath; try { bool? inSync = null; bool updateTargetOnSuccess = false; string eTag = null; try { if (!FsPath.IsRecycleBin(userFileSystemNewPath) && // When a file is deleted, it is moved to a Recycle Bin. !FsPath.AvoidSync(userFileSystemOldPath) && !FsPath.AvoidSync(userFileSystemNewPath)) { logger.LogMessage("Moving item in remote storage", userFileSystemOldPath, userFileSystemNewPath); // Read In-Sync state before move and set after move if (FsPath.Exists(userFileSystemOldPath)) { inSync = PlaceholderItem.GetItem(userFileSystemOldPath).GetInSync(); } eTag = await ETag.GetETagAsync(userFileSystemOldPath); ETag.DeleteETag(userFileSystemOldPath); IUserFileSystemItem userFileSystemItemOld = await virtualDrive.GetItemAsync <IUserFileSystemItem>(userFileSystemOldPath); await userFileSystemItemOld.MoveToAsync(userFileSystemNewPath); updateTargetOnSuccess = true; logger.LogMessage("Moved succesefully in remote storage", userFileSystemOldPath, userFileSystemNewPath); } } finally { if (resultContext != null) { resultContext.ReturnConfirmationResult(); } // This check is just to avoid extra error in the log. if (FsPath.Exists(userFileSystemNewPath)) { // Open file to preven reads and changes between GetFileDataSizeInfo() call and SetInSync() call. using (WindowsFileSystemItem userFileSystemWinItem = WindowsFileSystemItem.OpenReadAttributes(userFileSystemNewPath, FileMode.Open, FileShare.None)) { if ((eTag != null) && PlaceholderItem.IsPlaceholder(userFileSystemNewPath)) { await ETag.SetETagAsync(userFileSystemNewPath, eTag); } // 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, checking if a file is a placeholder. if (updateTargetOnSuccess && PlaceholderItem.IsPlaceholder(userFileSystemNewPath)) { PlaceholderItem placeholderNew = PlaceholderItem.GetItem(userFileSystemNewPath); // Update OriginalPath, so the item does not appear as moved. placeholderNew.SetOriginalPath(userFileSystemNewPath); if (inSync != null) { placeholderNew.SetInSync(inSync.Value); } else if ((placeholderNew is PlaceholderFile) && ((PlaceholderFile)placeholderNew).GetFileDataSizeInfo().ModifiedDataSize == 0) { placeholderNew.SetInSync(true); } await new UserFileSystemRawItem(userFileSystemNewPath).ClearStateAsync(); } } } } } catch (Exception ex) { string userFileSystemPath = FsPath.Exists(userFileSystemNewPath) ? userFileSystemNewPath : userFileSystemOldPath; await new UserFileSystemRawItem(userFileSystemPath).SetUploadErrorStateAsync(ex); // Rethrow the exception preserving stack trace of the original exception. System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex).Throw(); } }