Пример #1
0
        private async Task <byte[]> GetBytesAsyncInner([NotNull] string url, string cacheKey = null, TimeSpan?aliveTime             = null,
                                                       IProgress <long> progress             = null, CancellationToken cancellation = default)
        {
            try {
                if (cacheKey == null)
                {
                    cacheKey = GetTemporaryName(url);
                }

                var actualAliveTime = aliveTime ?? _cacheAliveTime;

                Tuple <byte[], DateTime> cache;
                lock (_cache) {
                    cache = _cache.GetValueOrDefault(cacheKey);
                }

                if (cache != null && cache.Item2 > DateTime.Now - actualAliveTime)
                {
                    return(cache.Item1);
                }

                var cacheFile = new FileInfo(FilesStorage.Instance.GetTemporaryFilename(_directory, cacheKey));
                if (cacheFile.Exists && cacheFile.LastWriteTime > DateTime.Now - actualAliveTime)
                {
                    try {
                        var data = await FileUtils.ReadAllBytesAsync(cacheFile.FullName).ConfigureAwait(false);

                        lock (_cache) {
                            _cache[cacheKey] = Tuple.Create(data, cacheFile.LastWriteTime);
                        }
                        return(data);
                    } catch (Exception e) {
                        Logging.Warning(e);
                        try {
                            cacheFile.Delete();
                        } catch {
                            // ignored
                        }
                    }
                }

                try {
                    var request = new HttpRequestMessage(HttpMethod.Get, url);
                    using (var timeout = new CancellationTokenSource(KunosApiProvider.OptionWebRequestTimeout))
                        using (var combined = CancellationTokenSource.CreateLinkedTokenSource(cancellation, timeout.Token))
                            using (var response = await HttpClientHolder.Get().SendAsync(request,
                                                                                         HttpCompletionOption.ResponseHeadersRead, combined.Token).ConfigureAwait(false)) {
                                byte[] data;
                                if (progress == null)
                                {
                                    data = await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
                                }
                                else
                                {
                                    using (var memory = new MemoryStream())
                                        using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false)) {
                                            await CopyToAsync(stream, memory, progress, cancellation).ConfigureAwait(false);

                                            cancellation.ThrowIfCancellationRequested();
                                            data = memory.ToArray();
                                        }
                                }

                                if (data.Length < 1e6)
                                {
                                    lock (_cache) {
                                        _cache[cacheKey] = Tuple.Create(data, DateTime.Now);
                                    }

                                    if (actualAliveTime > TimeSpan.Zero)
                                    {
                                        try {
                                            File.WriteAllBytes(cacheFile.FullName, data);
                                        } catch (Exception e) {
                                            Logging.Warning(e);
                                        }
                                    }
                                }

                                return(data);
                            }
                } catch (Exception e) {
                    if (!cancellation.IsCancellationRequested)
                    {
                        Logging.Warning(e);
                    }

                    if (cache != null)
                    {
                        return(cache.Item1);
                    }

                    if (cacheFile.Exists)
                    {
                        var data = await FileUtils.ReadAllBytesAsync(cacheFile.FullName).ConfigureAwait(false);

                        lock (_cache) {
                            _cache[cacheKey] = Tuple.Create(data, cacheFile.LastWriteTime);
                        }
                        return(data);
                    }

                    return(null);
                }
            } finally {
                _tasks.Remove(url);
            }
        }