/// <summary>
 /// Создаёт и возвращает новое задание по скачиванию указанных песен и последующему сохранению их на диск по указанному пути
 /// </summary>
 /// <param name="Songs">Список всех хидеров песен, файлы песен для которых следует скачать и вернуть. 
 /// Не может быть NULL или пустым.</param>
 /// <param name="UserAgent">User-Agent, который будет использоваться при выполнении запросов</param>
 /// <param name="FolderPath">Существующий путь на диске, по которому будут сохранены песни. 
 /// Если NULL, некорректный или не существует, будет выброшено исключение.</param>
 /// <param name="GenerateNewFilenames">Определяет, следует ли генерировать новое имя файла на основании тэгов песни (true), 
 /// или же использовать то имя файла, которое "пришло" с сервера (false). Если будет указана генерация нового, однако 
 /// получившееся имя будет некорректным, метод попытается его исправить. 
 /// Если же исправить не получится, будет использовано имя с сервера.</param>
 /// <param name="FilenameTemplate">Шаблон имени файла песни</param>
 /// <returns></returns>
 public static ReactiveDownloader CreateTask
     (IList<OneSongHeader> Songs, String UserAgent, String FolderPath, Boolean GenerateNewFilenames, String FilenameTemplate)
 {
     if (UserAgent.HasAlphaNumericChars() == false) { throw new ArgumentException("User-Agent не может быть пустым", "UserAgent"); }
     if (FilePathTools.IsValidFilePath(FolderPath) == false)
     {
         throw new ArgumentException
             ("Путь для сохранения файлов песен = '" + FolderPath.ToStringS("NULL") + "' некорректен", "FolderPath");
     }
     if(Songs == null) {throw new ArgumentNullException("Songs");}
     if(Songs.Any()==false) {throw new ArgumentException("Список песен для обработки не может быть пустым", "Songs");}
     if(GenerateNewFilenames == true && FilenameTemplate.HasAlphaNumericChars()==false)
     {throw new ArgumentException("Шаблон имени файла не может быть пуст, если требуется клиентская генерация имён файлов");}
     return new ReactiveDownloader(Songs, UserAgent, FolderPath, GenerateNewFilenames, FilenameTemplate);
 }
Example #2
0
 /// <summary>
 /// Пытается очистить от шелухи и возвратить URI
 /// </summary>
 /// <param name="Input"></param>
 /// <param name="ErrorMessage"></param>
 /// <returns></returns>
 internal static Uri TryFixReturnURI(String Input, out String ErrorMessage)
 {
     ErrorMessage = null;
     if (Input.HasAlphaNumericChars() == false)
     {
         ErrorMessage = "URI = '" + Input.ToStringS("NULL") + "' заведомо некорректен";
         return null;
     }
     const String main_domain = "http://myzuka.ru";
     const String download_domain = "http://fp";
     String temp_URI = Input.Trim(new char[2] { ' ', '"' });
     if (temp_URI.StartsWith(main_domain, StringComparison.OrdinalIgnoreCase) == false &&
         temp_URI.StartsWith(download_domain, StringComparison.OrdinalIgnoreCase) == false)
     {
         temp_URI = main_domain + temp_URI;
     }
     temp_URI = HttpTools.DecodeUri(temp_URI);
     Uri link_URI;
     Boolean res = Uri.TryCreate(temp_URI, UriKind.Absolute, out link_URI);
     if (res == false)
     {
         ErrorMessage = String.Format(
           "Невозможно корректно распарсить как абсолютный URI подстроку '{0}', полученную из строки '{1}'",
           temp_URI, Input);
         return null;
     }
     return link_URI;
 }
Example #3
0
 /// <summary>
 /// Асинхронно, без задержки вызывающего потока, скачивает и сохраняет на диск по указанному пути все песни, указанные в наборе, 
 /// выполняя запросы к серверу с указанной степенью паралеллизма и с указанным токеном отмены операции
 /// </summary>
 /// <param name="Songs">Список всех хидеров песен, файлы песен для которых следует скачать и вернуть</param>
 /// <param name="UserAgent">UserAgent, который будет использоваться при выполнении запросов</param>
 /// <param name="FolderPath">Существующий путь на диске, по которому будут сохранены песни. 
 /// Если NULL, некорректный или не существует, будет выброшено исключение.</param>
 /// <param name="GenerateNewFilenames">Определяет, следует ли генерировать новое имя файла на основании тэгов песни (true), 
 /// или же использовать то имя файла, которое "пришло" с сервера (false). Если будет указана генерация нового, однако 
 /// получившееся имя будет некорректным, метод попытается его исправить. 
 /// Если же исправить не получится, будет использовано имя с сервера.</param>
 /// <param name="FilenameTemplate"></param>
 /// <param name="CancToken">Токен отмены операции</param>
 /// <param name="MaxDegreeOfParallelism">Максимальное количество потоков, которое будет использоваться для запросов к серверу. 
 /// Если меньше 1, ограничение на количество потоков будет снято.</param>
 /// <returns></returns>
 public static async Task<IDictionary<OneSongHeader, Exception>> TryDownloadAndSaveAllSongsAsync
     (IList<OneSongHeader> Songs, String UserAgent,
         String FolderPath, Boolean GenerateNewFilenames, String FilenameTemplate,
         CancellationToken CancToken, Int32 MaxDegreeOfParallelism)
 {
     Songs.ThrowIfNullOrEmpty();
     if (UserAgent == null)
     {
         throw new ArgumentNullException("UserAgent");
     }
     if (FilePathTools.IsValidFilePath(FolderPath) == false)
     {
         throw new ArgumentException("Путь = '" + FolderPath.ToStringS("NULL") + "' некорректен", "FolderPath");
     }
     if (MaxDegreeOfParallelism < 1)
     {
         MaxDegreeOfParallelism = -1;
     }
     return await Task.Factory.StartNew<IDictionary<OneSongHeader, Exception>>(
         () => Core.TryDownloadAndSaveAllSongs(Songs, UserAgent, FolderPath, GenerateNewFilenames, FilenameTemplate, CancToken, MaxDegreeOfParallelism), 
         CancToken, TaskCreationOptions.LongRunning, TaskScheduler.Default);
 }
Example #4
0
        /// <summary>
        /// Скачивает и сохраняет на диск по указанному пути все песни, указанные в наборе, 
        /// выполняя запросы к серверу с указанной степенью паралеллизма и с указанным токеном отмены операции
        /// </summary>
        /// <param name="Songs">Список всех хидеров песен, файлы песен для которых следует скачать и вернуть</param>
        /// <param name="UserAgent">UserAgent, который будет использоваться при выполнении запросов</param>
        /// <param name="FolderPath">Существующий путь на диске, по которому будут сохранены песни. 
        /// Если NULL, некорректный или не существует, будет выброшено исключение.</param>
        /// <param name="GenerateNewFilenames">Определяет, следует ли генерировать новое имя файла на основании тэгов песни (true), 
        /// или же использовать то имя файла, которое "пришло" с сервера (false). Если будет указана генерация нового, однако 
        /// получившееся имя будет некорректным, метод попытается его исправить. 
        /// Если же исправить не получится, будет использовано имя с сервера.</param>
        /// <param name="FilenameTemplate"></param>
        /// <param name="CancToken">Токен отмены операции</param>
        /// <param name="MaxDegreeOfParallelism">Максимальное количество потоков, которое будет использоваться для запросов к серверу. 
        /// Если меньше 1, ограничение на количество потоков будет снято.</param>
        /// <returns>Словарь ключей и значений, где ключ - это поданный на вход хидер песни, а значение - возможное исключение, 
        /// которое возникло в процессе скачивания и сохранения песни, или же NULL, если песня была успешно скачана и сохранена.</returns>
        public static IDictionary<OneSongHeader, Exception> TryDownloadAndSaveAllSongs
            (IList<OneSongHeader> Songs, String UserAgent,
            String FolderPath, Boolean GenerateNewFilenames, String FilenameTemplate,
            CancellationToken CancToken, Int32 MaxDegreeOfParallelism)
        {
            Songs.ThrowIfNullOrEmpty();
            if (UserAgent == null) { throw new ArgumentNullException("UserAgent"); }
            if (FilePathTools.IsValidFilePath(FolderPath) == false) 
            {throw new ArgumentException("Путь = '" + FolderPath.ToStringS("NULL") + "' некорректен", "FolderPath");}
            if (MaxDegreeOfParallelism < 1) {MaxDegreeOfParallelism = -1;}


            ConcurrentDictionary<OneSongHeader, Exception> intermediate = 
                new ConcurrentDictionary<OneSongHeader, Exception>(MaxDegreeOfParallelism, Songs.Count);
            ParallelOptions opt = new ParallelOptions() { CancellationToken = CancToken, MaxDegreeOfParallelism = MaxDegreeOfParallelism };
            ParallelLoopResult p_res = Parallel.ForEach(Songs, opt, 
                (OneSongHeader song, ParallelLoopState pls, Int64 i) =>
                {
                    opt.CancellationToken.ThrowIfCancellationRequested();
                    if(pls.ShouldExitCurrentIteration){pls.Break();}
                    KeyValuePair<OneSongHeader, Exception> res =
                        Core.DownloadAndSaveOneSong(song, UserAgent, GenerateNewFilenames, FilenameTemplate, FolderPath, (Int32)i + 1);
                    intermediate.TryAdd(res.Key, res.Value);
                }
            );
            
            return intermediate;
        }