Skip to content

Instantly share code, notes, and snippets.

@joelverhagen
Created October 27, 2017 20:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joelverhagen/32e7264f17b6259de80ea4224e47b48f to your computer and use it in GitHub Desktop.
Save joelverhagen/32e7264f17b6259de80ea4224e47b48f to your computer and use it in GitHub Desktop.
Determine package size using NuGet V3 API

This is a demonstration of the various ways to get a package size (in bytes) using the NuGet V3 API.

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