/// <summary> /// Метод отправки файлов из локальной директории на Rdev по http /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void DirUpload_Click(object sender, EventArgs e) { try { // Получаем путь к директории с аудиокнигами var path = ConfigurationManager.AppSettings["Audiobooks"]; int counter = 0; // Заканчиваем работу метода если не удалось найти директорию с аудиокнигами if (!Directory.Exists(path)) { logger.Warning("Директория с аудиокнигами не существует!"); return; } // Получаем список файлов из директории (аудиокниги в директории представлены в виде .zip архива) var files = Directory.GetFiles(path); logger.Debug("Запущена загрузка аудиокниг из локальной директории"); logger.Log($"Количество файлов: {files.Count()}."); // Запускаем цикл на последовательный обход архива с аудиокнигами foreach (var file in files) { if (Path.GetExtension(file) != ".zip") { continue; } using (var zip = ZipFile.Open(file, ZipArchiveMode.Read, Encoding.GetEncoding(866))) { //Получаем список файлов var zipContent = zip.Entries; // Ищем txt файл со ссылкой на аудиокнигу var txtName = zipContent.FirstOrDefault(x => Path.GetExtension(x.Name.Replace('<', ' ').Replace('>', ' ')) == ".txt"); // Копируем содержимое файла в memory stream var memStream = new MemoryStream(); await txtName.Open().CopyToAsync(memStream); // Получаем содержимое файла string txtContnent = Encoding.ASCII.GetString(memStream.ToArray()); // Формируем объект аудиокниги var audiobook = new Audiobook { Title = Path.GetFileNameWithoutExtension(txtName.Name.Replace('<', ' ').Replace('>', ' ')), Url = txtContnent }; // Сохраняем аудиокнигу в таблицу скаченных аудиокниг await db.SaveDownloadAudiobook(audiobook); logger.Debug($"Попытка загрузки аудиокниги {audiobook.Title}, URL:{audiobook.Url}"); // Получаем все mp3 файлы var mp3Content = zipContent.Where(x => Path.GetExtension(x.Name.Replace('<', ' ').Replace('>', ' ')) == ".mp3").ToList(); int chapter = 0; logger.Log($"Аудиокнига {audiobook.Title} из {mp3Content.Count} аудиофайлов."); logger.Debug($"Проверяем была ли аудиокнига: {audiobook.Title} загружена ранее."); // Если книга полностью отдана на Rdev, идем к следующей if (db.IsUploadAudiobook(audiobook)) { logger.Warning($"Аудиокнига {audiobook.Title} была ранее передана на Rdev."); logger.Log($"Количество загруженных книг {++counter}."); continue; } logger.Debug($"Получаем ownerrecid для файла аудиокниги: {audiobook.Title}."); // Получаем идентификатор книги, если книга уже выгружалась на рдев но не все файлы были переданы // получаем значение идентификатора из бд иначе если это первая выгрузка формируем новый идентификатор Guid ownerRecId = db.GetOwnerRecid(audiobook); logger.Debug($"Запускаем upload аудиофайлов книги: {audiobook.Title}."); foreach (var entry in mp3Content) { using (var fs = entry.Open()) { Guid recId = Guid.NewGuid(); // Формируем объект отправляемого файла var sendedFile = new Audiofile() { Name = entry.Name, Chapter = ++chapter, OwnerRecid = ownerRecId.ToString(), AudiobookName = audiobook.Title, AudiobookUrl = audiobook.Url }; logger.Debug($"Проверяем отправлялся ли файл {sendedFile.Name} ранее."); // Проверям был ли отдан файл с таким названием и главой на Rdev, если да, переходим к следующей итерации цикла, // иначе отдаем файл if (db.IsUploadAudiofile(sendedFile)) { logger.Warning($"Файл {sendedFile.Name} уже отправлялся, переходим к следующему."); continue; } logger.Debug($"Отправляем аудиофайл: {sendedFile.Name}"); // Отправляем файл на Rdev await client.Upload(sendedFile, fs, recId); logger.Debug($"Сохраняем информацию о переданном файле {sendedFile.Name}"); // В случае если файл был успешно передан на Rdev (вернулся статус код 200) await db.SaveUploadAudiofile(sendedFile); logger.Success($"Информация о файле {sendedFile.Name} была успешно сохранена."); } } logger.Debug($"Все файлы аудиокниги {audiobook.Title} были переданны, сохраняем аудиокнигу в историю загрузок."); // Добавляем запись о полностью отданной на Rdev книге, если не было ошибки при передаче файлов await db.SaveUploadAudiobook(audiobook); logger.Success($"Информация об аудиокниге {audiobook.Title} была успешно сохранена."); logger.Debug($"Количество загруженных книг{++counter}"); } } } catch (Exception ex) { logger.Error(ex.Message); } }
/// <summary> /// Метод распаковывает архив с аудиокнигой и запускает пофайловую передачу на Rdev, /// после успешной передачи файла на сервер Rdev, сохраняет запись о файле в таблицу UploadAudiofile, /// после успешной передачи всей аудиокниге сохраняет в таблицу UploadAudiobook запись о книге /// </summary> /// <param name="audiobook"></param> /// <returns></returns> private async Task Upload(Audiobook audiobook) { try { logger.Log($"Проверяем была ли аудиокнига {audiobook.Title} полностью на Rdev."); // Если книга полностью отдана на Rdev, выходим из метода if (db.IsUploadAudiobook(audiobook)) { logger.Log($"Аудиокнига {audiobook.Title} была полностью отдана на Rdev, выходим из метода."); return; } logger.Log($"Получаем значение ownerrecid для аудиокниги {audiobook.Title}."); // Получаем идентификатор аудиокниги Guid ownerRecId = db.GetOwnerRecid(audiobook); logger.Log($"Запускаем чтение архива с аудиокнигой по адресу {fileName}."); // Запускаем пофайловую передачу файлов из архива на Rdev using (var zip = ZipFile.OpenRead(fileName)) { int chapter = 0; foreach (var entry in zip.Entries) { // Берем только mp3 файлы if (entry.FullName.EndsWith(".mp3", StringComparison.OrdinalIgnoreCase)) { logger.Log($"Запускаем выгрузку аудиофайла {entry.Name}."); // Получаем файл на отправку using (var fs = entry.Open()) { Guid recId = Guid.NewGuid(); // Формируем объект прдеставляющий файл для отправки на Rdev var file = new Audiofile() { Name = entry.Name, Chapter = ++chapter, OwnerRecid = ownerRecId.ToString(), AudiobookName = audiobook.Title, AudiobookUrl = audiobook.Url }; logger.Log($"Проверяем отправлялся ли аудиофайл {entry.Name} ранее на Rdev."); // Проверям был ли отдан файл с таким названием и главой на Rdev, если да, переходим к следующей итерации цикла, // иначе отдаем файл if (db.IsUploadAudiofile(file)) { logger.Log($"Аудиофайл {entry.Name} ранее был отправлен на Rdev, переходим к следующему."); continue; } logger.Log( $"Отправляем аудиофайл {entry.Name} на Rdev. Данный аудиофайл является {file.Chapter} главой аудиокниги." ); // Отправляем файл на Rdev await client.Upload(file, fs, recId); logger.Success($"Аудиофайл {entry.Name} был успешно отправлен на Rdev."); logger.Log("Сохраняем информацию по аудиофайлу в таблицу отданных аудиофайлов."); // Добавляем файл в таблицу отданных файлов await db.SaveUploadAudiofile(file); logger.Success("Сохранение прошло успешно."); } } } logger.Success($"Аудиокнига {audiobook.Title} была полностью передана на Rdev."); logger.Log($"Сохраняем информацию об аудиокниге {audiobook.Title} в таблицу отданных на Rdev аудиокниг."); // Добавляем запись о полностью отданной на Rdev книге await db.SaveUploadAudiobook(audiobook); logger.Success("Сохранение прошло успешно."); } } catch (Exception ex) { throw new Exception(ex.Message); } }
/// <summary> /// Метод отдачи файлов на Rdev /// </summary> /// <param name="file">Отдаваемый аудиофайл</param> /// <param name="stream">Поток с содержимым файла</param> /// <param name="recid">recid файла, для 1 главы значение recid совпадает с ownerrecid</param> /// <returns></returns> public async Task Upload(Audiofile file, Stream stream, Guid recid) { byte[] bytes = null; // Выгружаем файл в память using (var memoryStream = new MemoryStream()) { stream.CopyTo(memoryStream); bytes = memoryStream.ToArray(); } // Если файл представляет собой первую главу, то значению recid устанавливаем значение ownerrecid if (file.Chapter == 1) { recid = Guid.Parse(file.OwnerRecid); } // Устанавливаем js метод, который будет запущен на стороне Rdev var request = new UploadFileDto() { Method = "uploadaudiofile" }; // Задаем описание для передаваемых файлов, в данной реализации передаем по одному файлу за раз // Содержимое файла передается в виде строки Base64 т.к файлы > 3 Мб на передачу уходит немалое время + // нужно обратить внимание, чтобы после кодирования в строку регистр символов не изменялся до этапа декодирования var files = new List <FileDescription>() { new FileDescription() { RecId = recid, DeviceId = Guid.Parse("7fce47ab-4fa2-4b81-aa06-d49223442d07"), Recdescription = file.AudiobookName, Mediatype = "audiobook", Chapter = file.Chapter, Ownerrecid = Guid.Parse(file.OwnerRecid), LocalDevicePathUpload = Path.GetFileName(file.AudiobookUrl), Name = $"{recid.ToString()}.mp3", // Описывает непосредственно файл Content = Convert.ToBase64String(bytes), // Описывает непосредственно файл Size = bytes.Length / 1024 } }; // Устанавливаем описание файлов в json объект fields request.Fields = new FilesItemDto() { Files = files }; string json = JsonConvert.SerializeObject(request); var content = new StringContent(json, Encoding.UTF8, "application/json"); // Выполняем запрос на Rdev using (var response = await client.PostAsync(rdevUrl, content).ConfigureAwait(false)) { if (response.StatusCode != HttpStatusCode.OK) { throw new Exception(await response.Content.ReadAsStringAsync()); } } }