public async Task Download(AudioBookDetailResult book) { var newBook = _audioBooks.Where(a => a.Book.Id == book.Id).FirstOrDefault(); if (newBook == null) { newBook = new MyAudioBook { Book = book, Path = $"{Session.Instance.GetDataDir()}", Filename = $"{book.Id}.zip", TmpFolder = null, Progress = 0, StatusDescription = "Pendiente de descarga", ErrorCode = 0, StatusKey = STATUS_PENDING }; _audioBooks.Add(newBook); } else { newBook.TmpFolder = null; newBook.Progress = 0; newBook.StatusDescription = "Pendiente de descarga"; newBook.ErrorCode = 0; newBook.StatusKey = STATUS_PENDING; } OnProgress?.Invoke(newBook); // save books await SaveBooks(); // process download queue #pragma warning disable 4014 Task.Run(() => ProcessDownloadQueue()); #pragma warning restore 4014 }
private void ProcessDownloadQueue() { if (_isProcessingDownload) { return; } _isProcessingDownload = true; while ((_currentAudioBook = GetNextDownloadItem()) != null) { if (_currentAudioBook == null) { _isProcessingDownload = false; return; } _cancel = false; var link = AsyncHelper.RunSync(() => AudioLibrary.Instance.GetAudioBookLink(_currentAudioBook.Book.Id)); if (link == null) { _currentAudioBook.StatusDescription = "Enlace de descarga no encontrado"; _currentAudioBook.StatusKey = STATUS_ERROR; _isProcessingDownload = false; // Remove download from the list int index = _audioBooks.FindIndex(f => f.Book.Id == _currentAudioBook.Book.Id); if (index > -1) { _audioBooks.RemoveAt(index); } AsyncHelper.RunSync(() => SaveBooks()); OnProgress?.Invoke(_currentAudioBook); return; } // download file var zipFile = $"{Session.Instance.GetDataDir()}/{_currentAudioBook.Book.Id}.zip"; if (File.Exists(zipFile)) { File.Delete(zipFile); } // Initialize web client var webClient = new WebClient(); webClient.DownloadProgressChanged += _webClient_DownloadProgressChanged; webClient.DownloadFileCompleted += _webClient_DownloadFileCompleted; webClient.DownloadFileAsync(new Uri(link), zipFile); while (webClient.IsBusy) { if (_cancel) { // Remove download from the list int index = _audioBooks.FindIndex(f => f.Book.Id == _currentAudioBook.Book.Id); if (index > -1) { _audioBooks.RemoveAt(index); } AsyncHelper.RunSync(() => SaveBooks()); webClient.CancelAsync(); break; } Thread.Sleep(100); } if (_cancel) { _cancel = false; } else { _currentAudioBook.StatusDescription = "Preparando audiolibro"; _currentAudioBook.StatusKey = STATUS_INSTALLING; _currentAudioBook.TmpFolder = $"{DateTime.Now.Ticks.ToString()}"; AsyncHelper.RunSync(() => SaveBooks()); OnProgress?.Invoke(_currentAudioBook); try { // Unzip using (ZipArchive archive = ZipFile.OpenRead(zipFile)) { double totalBytes = archive.Entries.Sum(e => e.Length); long currentBytes = 0; var targetPath = $"{Session.Instance.GetDataDir()}/{_currentAudioBook.Book.Id}"; // clean up if exists if (Directory.Exists(targetPath)) { Directory.Delete(targetPath, true); } Directory.CreateDirectory(targetPath); foreach (ZipArchiveEntry entry in archive.Entries) { if (!string.IsNullOrEmpty(entry.Name)) { string fileName = Path.Combine($"{targetPath}", Path.GetFileName(entry.FullName)); using (Stream inputStream = entry.Open()) using (Stream outputStream = File.OpenWrite(fileName)) { Stream progressStream = new StreamWithProgress(outputStream, null, new BasicProgress <int>(i => { currentBytes += i; _currentAudioBook.Progress = (int)(currentBytes / totalBytes); OnProgress?.Invoke(_currentAudioBook); }) ); inputStream.CopyTo(progressStream); } File.SetLastWriteTime(fileName, entry.LastWriteTime.LocalDateTime); } } } } catch { _isProcessingDownload = false; _currentAudioBook.StatusKey = STATUS_ERROR; _currentAudioBook.StatusDescription = "Error: no se ha podido extraer el contendido del audiolibro"; OnProgress?.Invoke(_currentAudioBook); AsyncHelper.RunSync(() => SaveBooks()); return; } // Read daisy format and generate a ncc.json file with all the book content prepared for the audio player var nccIndex = $"{Session.Instance.GetDataDir()}/{_currentAudioBook.Book.Id}/ncc.html"; if (!File.Exists(nccIndex)) { _isProcessingDownload = false; _currentAudioBook.StatusKey = STATUS_ERROR; _currentAudioBook.StatusDescription = "Error: formato del audiolibro incorrecto. Índice no encontrado."; OnProgress?.Invoke(_currentAudioBook); AsyncHelper.RunSync(() => SaveBooks()); return; } DaisyBook dbook = new DaisyBook(); dbook.Load(nccIndex); dbook.Id = _currentAudioBook.Book.Id; string dbookStr = JsonConvert.SerializeObject(dbook); File.WriteAllText($"{Session.Instance.GetDataDir()}/{_currentAudioBook.Book.Id}/ncc.json", dbookStr); // clean up .zip file File.Delete($"{Session.Instance.GetDataDir()}/{_currentAudioBook.Book.Id}.zip"); _currentAudioBook.StatusKey = STATUS_COMPLETED; _currentAudioBook.StatusDescription = "Completado"; OnProgress?.Invoke(_currentAudioBook); AsyncHelper.RunSync(() => SaveBooks()); } _isProcessingDownload = false; } }