/// <summary> /// Retrieve the necessary URLs to process folders related operations /// </summary> /// <param name="folder">DirectoryInfo of the folder to process</param> /// <param name="list">The Targeted SharePoint Online Library</param> /// <param name="localPath">Local Path selected by user - Used ton normalize the urls</param> /// <returns>ItemURLs - Object containing the Normalized path and the ServerRelativeURL</returns> public ItemURLs formatUrl(DirectoryInfo folder, List list, string localPath) { ItemURLs folderUrls = new ItemURLs(); //We retrieve the folder Normalized path string localPathNormalized = localPath.Replace("/", "\\"); string folderPath = folder.FullName.Replace("/", "\\"); string folderPathNormalized = folderPath.Replace(localPathNormalized, ""); string folderPathNormalizedFinal = folderPathNormalized.Replace("\\", "/"); folderUrls.ItemNormalizedPath = folderPathNormalizedFinal; //We retrieve the folder ServerRelativeUrl string libURL = list.RootFolder.ServerRelativeUrl.ToString(); string serverRelativeURL = libURL + "/" + folderPathNormalizedFinal; folderUrls.ServerRelativeUrl = serverRelativeURL; return(folderUrls); }
/// <summary> /// Retrieve the necessary URLs to process file related operations /// </summary> /// <param name="folder">FileInfo of the file to process</param> /// <param name="list">The Targeted SharePoint Online Library</param> /// <param name="localPath">Local Path selected by user - Used ton normalize the urls</param> /// <returns>ItemURLs - Object containing the Normalized path and the ServerRelativeURL</returns> public ItemURLs formatUrl(FileInfo file, List list, string localPath) { ItemURLs itemUrls = new ItemURLs(); //We retrieve the ItemNormalized path string libURL = list.RootFolder.ServerRelativeUrl.ToString(); string localPathNormalized = localPath.Replace("/", "\\"); string filePath = file.FullName.Replace("/", "\\"); string fileNormalizedPath = filePath.Replace(localPathNormalized, ""); string fileNormalizedPathfinal = fileNormalizedPath.Replace("\\", "/"); itemUrls.ItemNormalizedPath = fileNormalizedPathfinal; //We contruct the item ServerRelativeUrl string serverRelativeURL = libURL + "/" + fileNormalizedPathfinal; itemUrls.ServerRelativeUrl = serverRelativeURL; return(itemUrls); }
/// <summary> /// BackgroundWorker Work event: /// Copy file and folders from the path selected to the target SharePoint Online library /// </summary> /// <param name="sender">Btn_Copy</param> /// <param name="e">OnClick()</param> private void bw_Dowork(object sender, DoWorkEventArgs e) { //[RESULT/LOG] We instanciate the repporting object Reporting repport = new Reporting(this.DocLib, this.Context.Web.ServerRelativeUrl); //[LOG:Verbose] We create the log object and log Local Path formating CopyLog log = new CopyLog(CopyLog.Status.Verbose, "Local path formating", LocalPath, ""); repport.writeLog(log); try { //We ensure the localpath endwith "/" for further formating actions if (!this.LocalPath.EndsWith("/") || !this.LocalPath.EndsWith("\\")) { this.LocalPath = this.LocalPath + "\\"; } //[LOG:OK] Local Path formating : Log success log.ActionStatus = CopyLog.Status.OK; repport.writeLog(log); //[LOG:Verbose] Local file retrieve log.update(CopyLog.Status.Verbose, "Local file retrieve", LocalPath, ""); repport.writeLog(log); //We retrive the list of DirectoryInfo and FileInfo List <FileInfo> files = FileLogic.getFiles(LocalPath); List <DirectoryInfo> folders = FileLogic.getSourceFolders(LocalPath); //[LOG:OK] Local file retrieve log.ActionStatus = CopyLog.Status.OK; repport.writeLog(log); //We instanciate the SPOLogic object to interact with SharePoint Online SPOLogic ctx = new SPOLogic(Context); //[LOG:Verbose] Checking library log.update(CopyLog.Status.Verbose, "Checking library", LocalPath, ""); repport.writeLog(log); //We enable Folder creation for the SharePoint Online library and ensure the Hash column exist bw.ReportProgress(0, "Checking Library"); List list = ctx.setLibraryReadyForPRocessing(this.DocLib); //[LOG:OK] Checking library log.ActionStatus = CopyLog.Status.OK; repport.writeLog(log); //[LOG:Verbose] Online ListItem retrieve log.update(CopyLog.Status.Verbose, "Online ListItem retrieve", LocalPath, ""); repport.writeLog(log); // We retrieve all listitems in the library bw.ReportProgress(0, "Retrieving ListItems"); List <ListItem> onlineListItem = ctx.GetAllDocumentsInaLibrary(this.DocLib); //[LOG:OK] Online ListItem retrieve log.ActionStatus = CopyLog.Status.OK; repport.writeLog(log); #region Folder Creation //[LOG:Title] Folder creation beggins log.update("[Starting Folder Creation process]"); repport.writeLog(log); var rootFolder = list.RootFolder; Context.Load(rootFolder); Context.ExecuteQuery(); //We set the index to display progression int i = 0; int count = 0; foreach (DirectoryInfo folder in folders) { //Progression display i++; double percentage = (double)i / folders.Count; int advancement = Convert.ToInt32(percentage * 100); bw.ReportProgress(advancement, $"Checking folders - {advancement}%\n{i}/{folders.Count}"); //We check for pending cancellation if (bw.CancellationPending == true) { //[LOG:CANCEL] Cancellation log log.update("[Process Cancelled]"); repport.writeLog(log); //We cancel the backgroundWorker and return e.Cancel = true; return; } //If no cancellation, we launch the copy folder process else { //[LOG:Verbose] Folder Creation log.update(CopyLog.Status.Verbose, "Folder creation", folder.FullName, ""); repport.writeLog(log); //We process the folder CopyStatus copyStatus = ctx.copyFolderToSPO(folder, list, LocalPath, onlineListItem); //[LOG:OK] Folder Creation log.ActionStatus = CopyLog.Status.OK; if (copyStatus != null) { //[LOG:OK] Folder Creation update path log.ItemPath = copyStatus.Path; log.Comment = copyStatus.Comment; repport.writeLog(log); //[RESULT] Folder Creation repport.writeResult(copyStatus); } else { //We skip writing result for the rootfolder repport.writeLog(log); } } } i = 0; count = 0; foreach (FoldersToProcess folder in ctx.FoldersToUpload) { //Progression display i++; double percentage = (double)i / folders.Count; int advancement = Convert.ToInt32(percentage * 100); bw.ReportProgress(advancement, $"Batching folders upload - {advancement}%\n{i}/{folders.Count}"); count++; var myFolder = rootFolder.Folders.Add(folder.ItemUrls.ServerRelativeUrl); if (count >= this.BatchRequestSize) { bw.ReportProgress(advancement, "Uploading folders batch"); Context.RequestTimeout = -1; Context.ExecuteQuery(); count = 0; } } bw.ReportProgress(0, "Finalising folders upload"); Context.RequestTimeout = -1; Context.ExecuteQuery(); i = 0; count = 0; foreach (FoldersToProcess folder in ctx.FoldersToUpload) { //Progression display i++; double percentage = (double)i / folders.Count; int advancement = Convert.ToInt32(percentage * 100); bw.ReportProgress(advancement, $"Batching folders metadata - {advancement}%\n{i}/{folders.Count}"); //We update metadate ListItem listitemFolder = Context.Web.GetListItem(folder.ItemUrls.ServerRelativeUrl); listitemFolder["Created"] = folder.Created; listitemFolder["Modified"] = folder.Modified; listitemFolder.Update(); count++; if (count >= this.BatchRequestSize) { bw.ReportProgress(advancement, "Uploading folders metadata batch"); Context.RequestTimeout = -1; Context.ExecuteQuery(); count = 0; } } bw.ReportProgress(0, "Finalising folders Metadata"); Context.RequestTimeout = -1; Context.ExecuteQuery(); #endregion #region FileCopy //[LOG:Title] File upload beggins log.update("[Starting File Upload process]"); repport.writeLog(log); //We reset the progression index i = 0; foreach (FileInfo file in files) { //Progression display i++; double percentage = (double)i / files.Count; int advancement = Convert.ToInt32(percentage * 100); bw.ReportProgress(advancement, $"Checking files - {advancement}%\n{i}/{files.Count}"); //Check if Cancellation is pending if (bw.CancellationPending == true) { //[LOG:CANCEL] Cancellation log log.update("[Process Cancelled]"); repport.writeLog(log); //We cancel the backgroundWorker and return e.Cancel = true; return; } //If no cancellation, we launch the copy file process else { //[LOG:Verbose] File Upload log.update(CopyLog.Status.Verbose, "File upload", file.FullName, ""); repport.writeLog(log); //We copy the file CopyStatus copyStatus = ctx.copyFileToSPO(file, list, LocalPath, onlineListItem); //[LOG:OK] File Upload log.ActionStatus = CopyLog.Status.OK; log.ItemPath = copyStatus.Path; log.Comment = copyStatus.Comment; //[RESULT/LOG: OK] File Upload repport.writeLog(log); repport.writeResult(copyStatus); } } #endregion #region Item Deletion //We handle the delete old items checkbox feature if (this.DeleteOldItems == true) { //[LOG:Verbose] Online ListItem retrieve log.update(CopyLog.Status.Verbose, "Online ListItem retrieve", LocalPath, ""); repport.writeLog(log); // We retrieve all listitems in the library and divide files and folders bw.ReportProgress(0, "Retrieving ListItems"); onlineListItem = ctx.GetAllDocumentsInaLibrary(this.DocLib); List <ListItem> onlineFiles = ctx.GetOnlyFiles(onlineListItem); List <ListItem> onlineFolders = ctx.GetOnlyFolders(onlineListItem); //[LOG:OK] Online ListItem retrieve log.ActionStatus = CopyLog.Status.OK; repport.writeLog(log); //[LOG:Title] File deletion beggins log.update("[Starting File Deletion process]"); repport.writeLog(log); #region File Deletion //We retrieve all the formated urls from local source files List <ItemURLs> itemsUrls = new List <ItemURLs>(); foreach (FileInfo file in files) { ItemURLs itemUrl = ctx.formatUrl(file, list, LocalPath); itemsUrls.Add(itemUrl); } //We reset the progression index i = 0; count = 0; foreach (ListItem onlineFile in onlineFiles) { //Progression display i++; double percentage = (double)i / onlineFiles.Count; int advancement = Convert.ToInt32(percentage * 100); bw.ReportProgress(advancement, $"Checking old files - {advancement}%\n{i}/{onlineFiles.Count}"); //Check if Cancellation is pending if (bw.CancellationPending == true) { //[LOG:CANCEL] Cancellation log log.update("[Process Cancelled]"); repport.writeLog(log); //We cancel the backgroundWorker and return e.Cancel = true; return; } //If no cancellation, we launch the file deletion process else { //[LOG:Verbose] File Deletion log.update(CopyLog.Status.Verbose, "File deletion", (string)onlineFile["FileLeafRef"], ""); repport.writeLog(log); //Attempt to delete the file if necessary CopyStatus copystat = ctx.CheckItemToDelete(itemsUrls, list, LocalPath, onlineFile); if (copystat.Status == CopyStatus.ItemStatus.Deleted) { count++; ListItem item = list.GetItemById((Int32)onlineFile["ID"]); item.DeleteObject(); } if (count >= this.BatchRequestSize) { count = 0; Context.ExecuteQuery(); } //[LOG:OK] File Deletion log.ActionStatus = CopyLog.Status.OK; log.ItemPath = copystat.Path; log.Comment = copystat.Comment; //[RESULT/LOG: OK] File Deletion repport.writeLog(log); repport.writeResult(copystat); } } bw.ReportProgress(0, "Deleting old files"); Context.RequestTimeout = -1; Context.ExecuteQuery(); #endregion #region Folder Deletion //Folder deletion //We retrieve all the formated urls from local source folders List <ItemURLs> folderUrls = new List <ItemURLs>(); foreach (DirectoryInfo folder in folders) { ItemURLs itemUrl = ctx.formatUrl(folder, list, LocalPath); folderUrls.Add(itemUrl); } //We reset the progression index i = 0; count = 0; foreach (ListItem onlineFolder in onlineFolders) { //Progression display i++; Double percentage = (double)i / onlineFolders.Count; int advancement = Convert.ToInt32(percentage * 100); bw.ReportProgress(advancement, $"Checking old folders - {advancement}%\n{i}/{onlineFolders.Count}"); //Check if Cancellation is pending if (bw.CancellationPending == true) { //[LOG:CANCEL] Cancellation log log.update("[Process Cancelled]"); repport.writeLog(log); //We cancel the backgroundWorker and return e.Cancel = true; return; } //If no cancellation, we launch the folder deletion process else { //[LOG:Verbose] Folder Deletion log.update(CopyLog.Status.Verbose, "Folder deletion", (string)onlineFolder["FileLeafRef"], ""); repport.writeLog(log); //Attempt to delete the file if necessary CopyStatus copystat = ctx.CheckItemToDelete(folderUrls, list, LocalPath, onlineFolder); //Change the item type to folder for result purpose copystat.Type = CopyStatus.ItemType.Folder; int pathRootFolderCount = FileLogic.isRootFolder(list.RootFolder.ServerRelativeUrl); int pathFolderCount = FileLogic.isRootFolder(copystat.Path); if ((pathFolderCount - pathRootFolderCount) == 1 && copystat.Status == CopyStatus.ItemStatus.Deleted) { count++; ListItem item = list.GetItemById((Int32)onlineFolder["ID"]); item.DeleteObject(); } if (count >= this.BatchRequestSize) { Context.RequestTimeout = -1; try { Context.ExecuteQuery(); } catch (Exception ex) { if (!ex.Message.Contains("Item does not exist. It may have been deleted by another user.")) { throw ex; } } } //[LOG:OK] Folder Deletion log.ActionStatus = CopyLog.Status.OK; log.ItemPath = copystat.Path; log.Comment = copystat.Comment; //[RESULT/LOG: OK] Folder Deletion repport.writeLog(log); repport.writeResult(copystat); } } bw.ReportProgress(0, "Deleting old folders"); Context.RequestTimeout = -1; try { Context.ExecuteQuery(); } catch (Exception ex) { if (!ex.Message.Contains("Item does not exist. It may have been deleted by another user.")) { throw ex; } } #endregion } #endregion } catch (Exception ex) { //We cancel the backgroundWorker if an exception is not handled so far MessageBox.Show(ex.Message); bw.CancelAsync(); e.Cancel = true; //[LOG:ERROR] Error log log.ActionStatus = CopyLog.Status.Error; log.Comment = ex.Message; repport.writeLog(log); //[RESULT:ERROR] Error result CopyStatus copyError = new CopyStatus { Comment = ex.Message, Name = log.ItemPath, Path = log.ItemPath, Status = CopyStatus.ItemStatus.Error }; repport.writeResult(copyError); } }
/// <summary> /// Copy folder to a SharePoint Online Site library /// </summary> /// <param name="folder">Folder to copy</param> /// <param name="list">List to copy folder to</param> /// <param name="localPath">Local Path selected by user</param> /// <returns>CopyStatus - the result from processing</returns> public CopyStatus copyFolderToSPO(DirectoryInfo folder, List list, string localPath, List <ListItem> onlineListItem) { //We instanciate the CopyStatus object to return CopyStatus copyStat = new CopyStatus { Name = folder.Name, Type = CopyStatus.ItemType.Folder, Path = folder.FullName.Remove(0, localPath.Length) }; //We retrieve the normalized Urls (ItemNormalized path and ServerRelativeUrl) ItemURLs folderUrls = formatUrl(folder, list, localPath); //We stop processing if we detect the RootFolder (user selected path) if (folderUrls.ItemNormalizedPath == "") { return(null); } //If the folder does not exist we create it if (checkFolderExist(folderUrls.ServerRelativeUrl, onlineListItem) == false) { /* * //We create the folder ListITemCreationInformation * ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation(); * itemCreateInfo.UnderlyingObjectType = FileSystemObjectType.Folder; * itemCreateInfo.LeafName = folderUrls.ItemNormalizedPath; * * //We create the folder * ListItem newItem = list.AddItem(itemCreateInfo); * * //We update the folder metadata * * * * Context.ExecuteQuery(); * * //We update the CopyStatus accordingly * copyStat.Status = CopyStatus.ItemStatus.Created; * copyStat.Comment = "Folder not found online - created"; * * return copyStat; * */ FoldersToProcess folderToProcess = new FoldersToProcess { ItemUrls = folderUrls, Created = folder.CreationTimeUtc, Modified = folder.CreationTimeUtc }; this.FoldersToUpload.Add(folderToProcess); /* * var rootFolder = list.RootFolder; * Context.Load(rootFolder); * Context.ExecuteQuery(); * var myFolder = rootFolder.Folders.Add(folderUrls.ServerRelativeUrl); * Context.ExecuteQuery(); * * //We update metadate * ListItem listitemFolder = Context.Web.GetListItem(folderUrls.ServerRelativeUrl); * listitemFolder["Created"] = folder.CreationTimeUtc; * listitemFolder["Modified"] = folder.CreationTimeUtc; * listitemFolder.Update(); * Context.ExecuteQuery(); */ //We update the CopyStatus accordingly copyStat.Status = CopyStatus.ItemStatus.Created; copyStat.Comment = "Folder not found online - created"; return(copyStat); } //The folder allready exists else { //We update the CopyStatus accordingly copyStat.Status = CopyStatus.ItemStatus.Skiped; copyStat.Comment = "Folder found online - skiped"; return(copyStat); } }