This is a demonstration of the various ways to get a package size (in bytes) using the NuGet V3 API.
Created
October 27, 2017 20:23
-
-
Save joelverhagen/32e7264f17b6259de80ea4224e47b48f to your computer and use it in GitHub Desktop.
Determine package size using NuGet V3 API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Net.Http; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using NuGet.Common; | |
using NuGet.Frameworks; | |
using NuGet.Packaging.Core; | |
using NuGet.Protocol; | |
using NuGet.Protocol.Core.Types; | |
using NuGet.Versioning; | |
namespace ConsoleApp1 | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
MainAsync(args, CancellationToken.None).Wait(); | |
} | |
static async Task MainAsync(string[] args, CancellationToken token) | |
{ | |
// You can log to STDOUT using the following type, which is from NuGet.CommandLine.Xplat. | |
// var log = new CommandOutputLogger(LogLevel.Debug); | |
var log = NullLogger.Instance; | |
// NuGet.org | |
var sourceRepository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json", FeedType.HttpV3); | |
var packageIdentity = new PackageIdentity("NuGet.Versioning", NuGetVersion.Parse("4.3.0")); | |
// MyGet: | |
// var sourceRepository = Repository.Factory.GetCoreV3("https://www.myget.org/F/dotnet/api/v3/index.json", FeedType.HttpV3); | |
// var packageIdentity = new PackageIdentity("Microsoft.DotNet.AppDep", NuGetVersion.Parse("1.0.5-prerelease-00001")); | |
// This | |
var packageSizeFromCatalog = await GetPackageSizeFromCatalog(packageIdentity, sourceRepository, log, token); | |
var packageSizeFromPackageUrl = await GetPackageSizeFromPackageUrl(packageIdentity, sourceRepository, log, token); | |
Console.WriteLine($"Package size from catalog: {packageSizeFromCatalog} bytes"); | |
Console.WriteLine($"Package size from package URL: {packageSizeFromPackageUrl} bytes"); | |
} | |
private static async Task<long?> GetPackageSizeFromCatalog(PackageIdentity packageIdentity, SourceRepository sourceRepository, ILogger log, CancellationToken token) | |
{ | |
var registrationResource = await sourceRepository.GetResourceAsync<RegistrationResourceV3>(); | |
var packageMetadata = await registrationResource.GetPackageMetadata(packageIdentity, log, token); | |
if (packageMetadata == null) | |
{ | |
Console.WriteLine($"The package {packageIdentity} does not exist."); | |
return null; | |
} | |
var catalogItemUrl = packageMetadata.Value<string>("@id"); | |
Console.WriteLine($"Catalog item URL: {catalogItemUrl}"); | |
var httpSourceResource = await sourceRepository.GetResourceAsync<HttpSourceResource>(); | |
var catalogItem = await httpSourceResource.HttpSource.GetJObjectAsync( | |
new HttpSourceRequest(catalogItemUrl, log), | |
log, | |
token); | |
return catalogItem.Value<long>("packageSize"); | |
} | |
private static async Task<long?> GetPackageSizeFromPackageUrl(PackageIdentity packageIdentity, SourceRepository sourceRepository, ILogger log, CancellationToken token) | |
{ | |
// Find the package URL. | |
var dependencyInfoResource = await sourceRepository.GetResourceAsync<DependencyInfoResource>(); | |
var package = await dependencyInfoResource.ResolvePackage( | |
packageIdentity, | |
NuGetFramework.AnyFramework, | |
log, | |
token); | |
if (package == null) | |
{ | |
Console.WriteLine($"The package {packageIdentity} does not exist."); | |
return null; | |
} | |
Console.WriteLine($"Package URL: {package.DownloadUri.AbsoluteUri}"); | |
long? packageSize = null; | |
using (var httpClient = new HttpClient()) | |
{ | |
// Make a HEAD request to the package URL. | |
// We can't use NuGet's HttpSource here due to https://github.com/NuGet/Home/issues/6112. | |
using (var headRequest = new HttpRequestMessage(HttpMethod.Head, package.DownloadUri)) | |
using (var headResponse = await httpClient.SendAsync(headRequest)) | |
{ | |
if (headResponse.IsSuccessStatusCode && | |
headResponse.Content.Headers.ContentLength.HasValue) | |
{ | |
Console.WriteLine("Got Content-Length header."); | |
packageSize = headResponse.Content.Headers.ContentLength; | |
} | |
} | |
// If that didn't work, download the package to get the size. | |
if (!packageSize.HasValue) | |
{ | |
Console.WriteLine("Downloading package to determine file size."); | |
using (var getRequest = new HttpRequestMessage(HttpMethod.Get, package.DownloadUri)) | |
using (var getResponse = await httpClient.SendAsync(getRequest, HttpCompletionOption.ResponseHeadersRead)) | |
using (var getStream = await getResponse.Content.ReadAsStreamAsync()) | |
{ | |
getResponse.EnsureSuccessStatusCode(); | |
var buffer = new byte[16 * 1024]; | |
int read; | |
long totalBytes = 0; | |
while ((read = await getStream.ReadAsync(buffer, 0, buffer.Length)) > 0) | |
{ | |
totalBytes += read; | |
} | |
packageSize = totalBytes; | |
} | |
} | |
} | |
return packageSize; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment