예제 #1
0
        public JsonResult Recovery(Task task, TypeRecovery typeRecovery, IDictionary <string, string> nameAndValue, bool IsAPI = false)
        {
            #region Демо режим
            if (Platform.IsDemo)
            {
                return(Json(new Text("Операция недоступна в демо-режиме")));
            }
            #endregion

            DateTime DateRecovery = default(DateTime);

            #region Проверка данных
            if (string.IsNullOrWhiteSpace(task.Description))
            {
                return(Json(new Text("Имя задания не может быть пустым")));
            }

            if (string.IsNullOrWhiteSpace(task.Whence))
            {
                return(Json(new Text("Локальный каталог не может быть пустым")));
            }

            if (string.IsNullOrWhiteSpace(task.Where))
            {
                return(Json(new Text("Удаленный каталог не может быть пустым")));
            }

            switch (task.TypeSunc)
            {
            case TypeSunc.SFTP:
            case TypeSunc.FTP:
            {
                if (string.IsNullOrWhiteSpace(task.FTP.HostOrIP) || string.IsNullOrWhiteSpace(task.FTP.Login) || string.IsNullOrWhiteSpace(task.FTP.Passwd))
                {
                    return(Json(new Text("Настройки 'FTP/SFTP' имеют недопустимое значение")));
                }
                break;
            }

            case TypeSunc.WebDav:
            {
                if (string.IsNullOrWhiteSpace(task.WebDav.url) || string.IsNullOrWhiteSpace(task.WebDav.Login) || string.IsNullOrWhiteSpace(task.WebDav.Passwd))
                {
                    return(Json(new Text("Настройки 'WebDav' имеют недопустимое значение")));
                }
                break;
            }

            case TypeSunc.OneDrive:
            {
                if (string.IsNullOrWhiteSpace(task.OneDrive.ApplicationId) || string.IsNullOrWhiteSpace(task.OneDrive.RefreshToken))
                {
                    return(Json(new Text("Настройки 'OneDrive' имеют недопустимое значение")));
                }
                break;
            }
            }

            if (task.EncryptionAES && string.IsNullOrWhiteSpace(task.PasswdAES))
            {
                return(Json(new Text("Пароль для шифрования файлов не может быть пустым")));
            }

            if (typeRecovery == TypeRecovery.Date && nameAndValue.TryGetValue("TypeRecoveryToDate", out string DateRecoveryTostring) && !DateTime.TryParse(DateRecoveryTostring, out DateRecovery))
            {
                return(Json(new Text("Отметка бэкапа имеет неправильный формат")));
            }
            #endregion

            // Искать файлы только в текущем каталоге
            bool SearchToCurrentDirectory = false;
            if (nameAndValue.TryGetValue("SearchOption", out string SearchOption) && SearchOption == "CurrentDirectory")
            {
                SearchToCurrentDirectory = true;
            }

            // Выполняем задание в потоке
            ThreadPool.QueueUserWorkItem(ob =>
            {
                #region Добовляем задание в WorkNote
                CancellationToken cancellationToken = new CancellationToken();
                var WorkNoteNotation = new Notation()
                {
                    TaskId   = task.Id,
                    Category = "Восстановление",
                    Msg      = $"Задание: {task.Description}",
                    Time     = DateTime.Now,
                    More     = new List <More>()
                    {
                        new More("Состояние", "Выполняется поиск всех папок")
                    }
                };
                CoreDB.SyncBackupWorkNote.Add(WorkNoteNotation, cancellationToken);
                #endregion

                // Создание отчета по ошибкам
                Report report = new Report(task);

                // Выполняем задание
                Tools.Recovery(task, new RemoteServer(task.TypeSunc, task.FTP, task.WebDav, task.OneDrive, report, out _), WorkNoteNotation, out List <More> ResponseNameAndValue, typeRecovery, DateRecovery, SearchToCurrentDirectory);

                // Сохраняем отчет об ошибках (если есть ошибки)
                report.SaveAndDispose(ref ResponseNameAndValue);

                // Чистим WorkNote
                CoreDB.SyncBackupWorkNote.Take(cancellationToken);

                #region Сохраняем данные задание в базе
                SqlToMode.SetMode(SqlMode.Read);
                using (CoreDB coreDB = Service.Get <CoreDB>())
                {
                    // Добовляем задание в список завершеных операций
                    coreDB.SyncBackup_Notations.Add(new Notation()
                    {
                        TaskId   = task.Id,
                        Category = "Восстановление",
                        Msg      = $"Задание: {task.Description}",
                        Time     = DateTime.Now,
                        More     = ResponseNameAndValue,
                    });

                    // Сохраняем базу
                    coreDB.SaveChanges();
                }
                SqlToMode.SetMode(SqlMode.ReadOrWrite);
                #endregion
            });

            // Отдаем ответ
            if (IsAPI)
            {
                return(Json(new TrueOrFalse(true)));
            }
            return(Json(new Text("Задание добавлено на обработку")));
        }
예제 #2
0
        /// <summary>
        /// Восстановить данные
        /// </summary>
        /// <param name="task">Задания</param>
        /// <param name="serv">Удаленный сервер</param>
        /// <param name="WorkNoteNotation">Текущее задание в WorkNote</param>
        /// <param name="NameAndValue">Колекция для ответа в журнал</param>
        /// <param name="typeRecovery">Режим востановления файлов</param>
        /// <param name="DateRecovery">Отметка бекапа для востановления по дате</param>
        public static void Recovery(Models.SyncBackup.Tasks.Task task, RemoteServer serv, Notation WorkNoteNotation, out List <More> NameAndValue, TypeRecovery typeRecovery, DateTime DateRecovery)
        {
            try
            {
                #region Переменные
                // Список папок которые нужно пропустить
                var ListSkipFolders = new List <string>();

                // Время старта задания
                var TimeStartTask = DateTime.Now;

                // Количиство загруженых файлов и созданых папок
                int CountDownloadToFilesOK = 0, CountDownloadToFilesAll = 0, CountCreateToDirectoryOk = 0;

                // Общий размер загруженых файлов в byte
                long CountDownloadToBytes = 0;
                #endregion

                #region Получаем список всех папок
                var RemoteFolders = new List <DirectoryModel>();
                RemoteFolders.Add(new DirectoryModel()
                {
                    Folder             = task.Where,
                    RemoteCreated      = default(DateTime),
                    RemoteLastModified = DateTime.Now,
                });
                serv.ListAllDirectory(task.Where, ref RemoteFolders);
                #endregion

                // Проходим список всех папок
                foreach (var RemoteFolder in RemoteFolders)
                {
                    // Папки и их подпапки которые не нужно восстанавливать
                    if (ListSkipFolders.Exists(i => RemoteFolder.Folder.Contains(i)))
                    {
                        continue;
                    }

                    // Пропускаем удаленые папки
                    if (typeRecovery == TypeRecovery.Topical && RemoteFolder.Folder.Contains(".SyncRemove"))
                    {
                        continue;
                    }

                    #region Локальный метод - "GetLocalFolder"
                    string GetLocalFolder()
                    {
                        // Удаленный каталог
                        string where = ConvertPatchToUnix(task.Where);

                        // Локальный каталог
                        string whence = ConvertPatchToUnix(task.Whence);

                        // Результат
                        return(RemoteFolder.Folder.Replace(where, whence));
                    }
                    #endregion

                    // Локальная дириктория
                    string LocalFolder = GetLocalFolder();

                    #region Востановление по дате
                    if (typeRecovery == TypeRecovery.Date)
                    {
                        if (RemoteFolder.Folder.Contains(".SyncRemove"))
                        {
                            // Если дата модификации папки ниже отметки
                            if (RemoteFolder.RemoteLastModified < DateRecovery)
                            {
                                ListSkipFolders.Add(RemoteFolder.Folder);
                                continue;
                            }
                        }
                        else
                        {
                            // Если дата создания папки выше отметки
                            if (RemoteFolder.RemoteCreated > DateRecovery)
                            {
                                ListSkipFolders.Add(RemoteFolder.Folder);
                                continue;
                            }
                        }

                        // Удаляем 'SyncRemove' в 'LocalFolder'
                        LocalFolder = Regex.Replace(LocalFolder, @"\.SyncRemove\.-[0-9]+", "");
                    }
                    #endregion

                    // Создаем локальную папку
                    Directory.CreateDirectory(LocalFolder);
                    CountCreateToDirectoryOk++;

                    // Количиство потоков
                    int ActiveConnections = task.TypeSunc == TypeSunc.SFTP ? task.FTP.ActiveConnections : 1;

                    #region Загружаем файлы на локальный сервер
                    Parallel.ForEach(SortedFiles(serv.ListDirectoryAndFiles(RemoteFolder.Folder).Files, SortedToLocalTime: false), new ParallelOptions {
                        MaxDegreeOfParallelism = ActiveConnections
                    }, RemoteData =>
                    {
                        if (typeRecovery == TypeRecovery.Date)
                        {
                            // Ищем файл который ближе всего подходит к отметки бекапа
                            if (RemoteData.Value.FirstOrDefault(i => i.RemoteCreated < DateRecovery) is SortedModel item)
                            {
                                // Загружаем файл который подходит по дате
                                DownloadFile(item, RemoteData.Key);
                            }
                        }
                        else
                        {
                            // Загружаем актуальный файл
                            DownloadFile(RemoteData.Value[0], RemoteData.Key);

                            // Загружаем бекапы
                            if (typeRecovery == TypeRecovery.all)
                            {
                                // Пропускаем актуальный файл и загружаем остальные
                                foreach (var RemoteFile in RemoteData.Value.Skip(1))
                                {
                                    // Загружаем файл
                                    DownloadFile(RemoteFile, RemoteFile.Name.Replace(".sync.aes.", ".sync."));
                                }
                            }
                        }
                    });
                    #endregion

                    #region Обновляем WorkNote
                    if (CountDownloadToFilesOK > 0)
                    {
                        WorkNoteNotation.More = new List <More>
                        {
                            new More("Состояние", $"Выполняется {GetToWorkTime("")}"),
                            new More("Загружено файлов", $"{CountDownloadToFilesOK:N0}"),
                            new More("Получено данных", ToSize(CountDownloadToBytes))
                        };
                    }
                    #endregion

                    #region Локальный метод DownloadFile
                    void DownloadFile(FileModel RemoteFile, string LocalFileName)
                    {
                        // Пропускаем удаленые файлы
                        if (typeRecovery == TypeRecovery.Topical && RemoteFile.Name.Contains(".remove") || RemoteFile.FileSize < 1)
                        {
                            return;
                        }

                        // Пути к файлам
                        string LocalFilePatch  = LocalFolder + LocalFileName;
                        string RemoteFilePatch = (RemoteFolder.Folder + "/" + RemoteFile.Name).Replace("//", "/");

                        // Проверяем на существование файла
                        if (!task.EncryptionAES && File.Exists(LocalFilePatch) && (new FileInfo(LocalFilePatch)).Length == RemoteFile.FileSize)
                        {
                            return;
                        }

                        int CountReDownload = 0;

                        // Загружаем удаленый файл в локальную папку
                        ReDownloadFile : if (serv.DownloadFile(LocalFilePatch, RemoteFilePatch, task.EncryptionAES, task.PasswdAES, RemoteFile.FileSize))
                        {
                            CountDownloadToFilesOK++;
                            CountDownloadToBytes += RemoteFile.FileSize;
                        }
                        else
                        {
                            if (++CountReDownload < 3)  // 3 попытки что-бы загрузить файл
                            {
                                goto ReDownloadFile;
                            }
                        }

                        CountDownloadToFilesAll++;
                    }
                    #endregion
                }

                #region Локальный метод GetToWorkTime
                string GetToWorkTime(string arg)
                {
                    var WorkTime = (DateTime.Now - TimeStartTask);

                    if (WorkTime.TotalSeconds <= 60)
                    {
                        return("");
                    }

                    if (WorkTime.TotalMinutes <= 60)
                    {
                        return($"{arg}{(int)WorkTime.TotalMinutes} {EndOfText.get("минуту", "минуты", "минут", (int)WorkTime.TotalMinutes)}");
                    }

                    return($"{arg}{(int)WorkTime.TotalHours} {EndOfText.get("час", "часа", "часов", (int)WorkTime.TotalHours)}");
                }
                #endregion

                #region Локальный метод ToSize
                string ToSize(double bytes)
                {
                    string[] Suffix = { "Byte", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
                    int      index  = 0;

                    while (bytes >= 1024)
                    {
                        bytes /= 1024;
                        index++;
                    }

                    return($"{bytes:N3} {Suffix[index]}");
                }
                #endregion

                #region Выполнено
                NameAndValue = new List <More>()
                {
                    new More("Состояние", $"Выполнено {GetToWorkTime("за ")}")
                };

                if (CountCreateToDirectoryOk > 0)
                {
                    NameAndValue.Add(new More("Создано папок", $"{CountCreateToDirectoryOk:N0}"));
                }

                if (CountDownloadToFilesAll > 0)
                {
                    NameAndValue.Add(new More("Загружено файлов", $"{CountDownloadToFilesOK:N0} из {CountDownloadToFilesAll:N0}"));
                    NameAndValue.Add(new More("Получено данных", ToSize(CountDownloadToBytes)));
                }
                #endregion
            }
            catch (Exception ex)
            {
                NameAndValue = new List <More>()
                {
                    new More("Состояние", "Ошибка при выполнении задания"),
                    new More("Код", ex.ToString())
                };
            }

            // Отключаемся от сервера
            serv.Disconnect();
        }
예제 #3
0
 public JsonResult Recovery(Task tk, TypeRecovery type, IDictionary <string, string> value) => new SyncBackupFilesToTools().Recovery(tk, type, value);