예제 #1
0
        public Migration(ListCollection ListCollection, ClientContext ctx)
        {
            InitializeComponent();
            this.Context = ctx;

            this.BatchRequestSize = Convert.ToInt32(FileLogic.getXMLSettings("BatchRequestSize"));

            //We retrieve only document library from the ListCollection passed and populate the combobox
            foreach (List list in ListCollection)
            {
                if (list.BaseTemplate == 101)
                {
                    Cb_doclib.Items.Add(list.Title);
                }
            }

            //We set the top header of the window
            Lb_Top.Content          = "Select a local path and a library to synchronize";
            Img_SP.Visibility       = Visibility.Visible;
            Cb_doclib.SelectedIndex = 0;
            Lb_Connected.Content    = $"Connected to {ctx.Url}";

            //We set the backgroundWorker Delegates
            bw.DoWork += bw_Dowork;
            bw.WorkerReportsProgress = true;
            bw.RunWorkerCompleted   += bw_RunWorkerCompleted;
            bw.ProgressChanged      += bw_ProgressChanged;

            bw.WorkerSupportsCancellation = true;
        }
예제 #2
0
        public Migration(List odList, ClientContext ctx)
        {
            InitializeComponent();
            this.Context = ctx;

            this.BatchRequestSize = Convert.ToInt32(FileLogic.getXMLSettings("BatchRequestSize"));

            Cb_doclib.Items.Add(odList.Title);
            Cb_doclib.SelectedIndex = 0;

            //We set the top header of the window
            Lb_Top.Content       = "Select a local path to synchronize";
            Img_OD.Visibility    = Visibility.Visible;
            Lb_Connected.Content = $"Connected to {ctx.Url}";

            //We set the backgroundWorker Delegates
            bw.DoWork += bw_Dowork;
            bw.WorkerReportsProgress = true;
            bw.RunWorkerCompleted   += bw_RunWorkerCompleted;
            bw.ProgressChanged      += bw_ProgressChanged;

            bw.WorkerSupportsCancellation = true;
        }
예제 #3
0
        /// <summary>
        /// This method provide the logic to compare local and online file to choose either to copy or not
        /// </summary>
        /// <param name="file">File to copy</param>
        /// <param name="list">The Targeted SharePoint Online Library</param>
        /// <param name="localPath">Local Path selected by user</param>
        /// <returns>CopyStatus - The result of processing</returns>
        public CopyStatus copyFileToSPO(FileInfo file, List list, string localPath, List <ListItem> onlineListItem)
        {
            //We instanciate the CopyStatus object to return feedback from processing
            CopyStatus copystat = new CopyStatus()
            {
                Name = file.Name,
                Type = CopyStatus.ItemType.File,
                Path = file.FullName.Remove(0, localPath.Length)
            };

            //We set the variable for the using statement bellow
            ItemURLs         fileUrls;
            DateTime         created;
            DateTime         modified;
            string           localFileLength;
            string           localFileHash;
            OnlineFileStatus targetFileStat;

            // We retrieve the normalized Urls(ItemNormalized path and ServerRelativeUrl)
            fileUrls = formatUrl(file, list, localPath);

            //We retrieve the target file status
            targetFileStat = checkListItemExist(fileUrls.ServerRelativeUrl, onlineListItem);

            //We retrieve the local file metadata
            created         = file.CreationTimeUtc;
            modified        = file.LastWriteTimeUtc;
            localFileLength = file.Length.ToString();

            //using the FileStream, we compute the file hash
            using (FileStream fileStream = new FileStream(file.FullName, FileMode.Open))
            {
                localFileHash = FileLogic.hashFromLocal(fileStream);
            }

            //If the target item does not exist, we copy the file and set metadata
            if (targetFileStat.FileFound == OnlineFileStatus.FileStatus.NotFound)
            {
                //We copy the file and set metadata
                //Microsoft.SharePoint.Client.File.SaveBinaryDirect(Context, fileUrls.ServerRelativeUrl, fileStream, false);
                UploadFileSlicePerSlice(Context, list.Title, file.FullName, fileUrls.ServerRelativeUrl);
                setUploadedFileMetadata(fileUrls.ServerRelativeUrl, created, modified, localFileHash);

                //We update the CopyStatus accordingly
                copystat.Status  = CopyStatus.ItemStatus.Uploaded;
                copystat.Comment = "File not found online - Uploaded";

                return(copystat);
            }
            //If target item has no hash, we compare lenght to check if copy is necessary
            else if (targetFileStat.HashFound == OnlineFileStatus.HashStatus.NotFound)
            {
                //We retrieve the target file length
                string targetFileLength = getFileLenght(fileUrls.ServerRelativeUrl);

                //Local and Online Files are the same length, se we do not overwrite
                if (localFileLength == targetFileLength)
                {
                    //We update metadata to push the right value in the FileHash column
                    setUploadedFileMetadata(fileUrls.ServerRelativeUrl, created, modified, localFileHash);

                    //We update the CopyStatus accordingly
                    copystat.Status  = CopyStatus.ItemStatus.Skiped;
                    copystat.Comment = "File found online but not hash - files are the same length so we do not overwrite the online file";

                    return(copystat);
                }
                else//If the file are different length, we overwrite the file and set metadata
                {
                    //We copy the file and set metadata
                    //Microsoft.SharePoint.Client.File.SaveBinaryDirect(Context, fileUrls.ServerRelativeUrl, fileStream, true);
                    UploadFileSlicePerSlice(Context, list.Title, file.FullName, fileUrls.ServerRelativeUrl);
                    setUploadedFileMetadata(fileUrls.ServerRelativeUrl, created, modified, localFileHash);

                    //We update the CopyStatus accordingly
                    copystat.Status  = CopyStatus.ItemStatus.Overwrited;
                    copystat.Comment = "File found online but not hash - files are not the same length so we overwrite the online file";

                    return(copystat);
                }
            }
            else
            {
                //If files are the same Hash, we do not overwrite
                if (localFileHash == targetFileStat.Hash)
                {
                    //We update the CopyStatus accordingly
                    copystat.Status  = CopyStatus.ItemStatus.Skiped;
                    copystat.Comment = "File found online - files are the same hash so we do not overwrite the online file";

                    return(copystat);
                }
                else //The file are not the same hash, we overwrite it and set metadata
                {
                    //We copy the file and set metadata
                    //Microsoft.SharePoint.Client.File.SaveBinaryDirect(Context, fileUrls.ServerRelativeUrl, fileStream, true);
                    UploadFileSlicePerSlice(Context, list.Title, file.FullName, fileUrls.ServerRelativeUrl);
                    setUploadedFileMetadata(fileUrls.ServerRelativeUrl, created, modified, localFileHash);

                    //We update the CopyStatus accordingly
                    copystat.Status  = CopyStatus.ItemStatus.Overwrited;
                    copystat.Comment = "File found online - files are not the same hash so we overwrite the online file";

                    return(copystat);
                }
            }
        }
예제 #4
0
        /// <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);
            }
        }
예제 #5
0
 public SPOLogic(ClientContext ctx)
 {
     this.Context = ctx;
     FileLogic.ensureConfigFileExists();
     this.hashColumn = FileLogic.getXMLSettings("HashColumn");
 }