コード例 #1
0
        /// <summary>
        /// Downloads iwyu from default download repository.
        /// </summary>
        /// <remarks>
        /// Throws an exception if anything goes wrong (and there's a lot that can!)
        /// </remarks>
        /// <exception cref="OperationCanceledException">If cancellation token is used.</exception>
        static public async Task DownloadIWYU(string executablePath, DownloadProgressUpdate onProgressUpdate, CancellationToken cancellationToken)
        {
            string targetDirectory = Path.GetDirectoryName(executablePath);

            Directory.CreateDirectory(targetDirectory);
            string targetZipFile = Path.Combine(targetDirectory, "download.zip");

            // Delete existing zip file.
            try
            {
                File.Delete(targetZipFile);
            }
            catch { }

            // Download.
            onProgressUpdate("Connecting...", "", -1.0f);

            // In contrast to GetCurrentVersionOnline we're not using HttpClient here since WebClient makes downloading files so much nicer.
            // (in HttpClient we would need to do the whole buffering + queuing and file writing ourselves)
            using (var client = new WebClient())
            {
                var cancelRegistration = cancellationToken.Register(() =>
                {
                    client.CancelAsync();
                    throw new TaskCanceledException();
                });

                client.DownloadProgressChanged += (object sender, DownloadProgressChangedEventArgs e) =>
                {
                    int kbTodo       = (int)System.Math.Ceiling((double)e.TotalBytesToReceive / 1024);
                    int kbDownloaded = (int)System.Math.Ceiling((double)e.BytesReceived / 1024);
                    onProgressUpdate("Downloading", kbTodo > 0 ? $"{kbTodo} / {kbDownloaded} kB" : $"{kbDownloaded} kB", e.ProgressPercentage * 0.01f);
                };

                await client.DownloadFileTaskAsync(DownloadRepositorURL, targetZipFile);

                cancelRegistration.Dispose();
            }

            // Unpacking. Looks like there is no async api, so we're just moving this to a task.
            onProgressUpdate("Unpacking...", "", -1.0f);
            await Task.Run(() =>
            {
                using (var zipArchive = new ZipArchive(File.OpenRead(targetZipFile), ZipArchiveMode.Read))
                {
                    // Don't want to have the top level folder if any,
                    string topLevelFolderName = "";

                    for (int i = 0; i < zipArchive.Entries.Count; ++i)
                    {
                        var file = zipArchive.Entries[i];

                        string targetName       = file.FullName.Substring(topLevelFolderName.Length);
                        string completeFileName = Path.Combine(targetDirectory, targetName);

                        // If name is empty it should be a directory.
                        if (file.Name == "")
                        {
                            if (i == 0)    // We assume that if the first thing we encounter is a folder, it is a toplevel one.
                            {
                                topLevelFolderName = file.FullName;
                            }
                            else
                            {
                                Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
                            }
                        }
                        else
                        {
                            using (var destination = File.Open(completeFileName, FileMode.Create, FileAccess.Write, FileShare.None))
                            {
                                using (var stream = file.Open())
                                    stream.CopyTo(destination);
                            }
                        }

                        if (cancellationToken.IsCancellationRequested)
                        {
                            return;
                        }
                    }
                }
            }, cancellationToken);

            // Save version.
            onProgressUpdate("Saving Version", "", -1.0f);
            string version = await GetCurrentVersionOnline();

            File.WriteAllText(GetVersionFilePath(executablePath), version);
        }
コード例 #2
0
        private static async Task <byte[]> DownloadStreamToByteArrayAsync(HttpResponseMessage response, CancellationToken token, DownloadProgressUpdate updateCallback)
        {
            long totalSize = response.Content.Headers.ContentLength.GetValueOrDefault();

            DownloadProgress.Factory factory = new DownloadProgress.Factory(totalSize);

            using Stream responseStream = await response.Content.ReadAsStreamAsync();

            byte[] data = new byte[totalSize];
            using MemoryStream dataStream = new MemoryStream(data);

            byte[] buffer    = new byte[8192];
            int    totalRead = 0;
            int    readBytes;

            while (!token.IsCancellationRequested && (readBytes = await responseStream.ReadAsync(buffer, 0, buffer.Length, token)) > 0)
            {
                updateCallback?.Invoke(factory.Update(totalRead));
                await dataStream.WriteAsync(buffer, 0, readBytes, token);

                totalRead += readBytes;
            }

            updateCallback?.Invoke(factory.Update(totalRead));

            return(data);
        }
コード例 #3
0
 /// <summary>
 /// Asynchronously downloads the data from a given URL using a HTTP GET request
 /// </summary>
 /// <param name="url">The target to download</param>
 /// <param name="updateCallback">A callback method for giving feedback on the download progress</param>
 /// <returns></returns>
 /// <exception cref="ArgumentNullException"><paramref name="url"/> is null</exception>
 /// <exception cref="HttpRequestException">The request failed</exception>
 public static Task <WebResource> LoadAsync([NotNull] string url, [NotNull] DownloadProgressUpdate updateCallback)
 => LoadAsync(url, CancellationToken.None, updateCallback);
コード例 #4
0
        /// <summary>
        /// Asynchronously downloads the data from a given URL using a HTTP GET request
        /// </summary>
        /// <param name="url">The target to download</param>
        /// <param name="token">A token to cancel the download</param>
        /// <param name="updateCallback">A callback method for giving feedback on the download progress</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"><paramref name="url"/> is null</exception>
        /// <exception cref="HttpRequestException">The request failed</exception>
        public static async Task <WebResource> LoadAsync([NotNull] string url, CancellationToken token, [NotNull] DownloadProgressUpdate updateCallback)
        {
            if (url is null)
            {
                throw new ArgumentNullException(nameof(url));
            }

            Uri uri = new Uri(url);

            using HttpResponseMessage response = await HttpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead, token);

            response.EnsureSuccessStatusCode();

            byte[] data = await DownloadStreamToByteArrayAsync(response, token, updateCallback ?? delegate { });

            return(new WebResource(uri.AbsoluteUri, DataHelper.GenerateSha1(data), data.LongLength, new MemoryStream(data, false), !token.IsCancellationRequested));
        }