-1

I am trying to download pipeline artifacts from an Azure Devops Pipeline.

The artifacts are zip files. I have been referencing this post, https://andrewlock.net/downloading-artifacts-from-azure-devops-using-dotnet/ and am nearly there.

Problem is, when I go to extract my zip files to check the content windows explorer says they are empty. I have tried other tools as well, same thing. I know the artifact is valid and the download url is valid, because I can break on entry to the following function and check the url. It matches up with what I get if I use the web UI.

Has to be something I am doing wrong with the download/creation of the zip file. Any help would be appreciated.

static private async Task DownloadArtifactWithHttpClient(string artifactDownloadUrl, string artifactName, string downloadPath)
{
    try
    {
        var localZipFilePath = downloadPath + $"\\{artifactName}.zip";

        // Use HttpClient to download the artifact
        using (var tempClient = new HttpClient())
        {
            // Send request to the DownloadUrl specificed in the BuildArtifact
            HttpResponseMessage response = await tempClient.GetAsync(artifactDownloadUrl);

            if (!response.IsSuccessStatusCode)
            {
                // Something went wrong, shouldn't happen
                throw new Exception($"Error downloading artifact: {response.StatusCode}:{response.ReasonPhrase}");
            }

            // Save the stream to a file
            using (Stream zipFile = File.Create(localZipFilePath))
            {
                await response.Content.CopyToAsync(zipFile);
            }
        }

        // All done!
        Console.WriteLine($"Done downloading too, {localZipFilePath}");
    }
    catch (Exception ex)
    {
        Console.WriteLine("Exception: " + ex.Message);
        if (ex.InnerException != null) Console.WriteLine("Detailed Info: " + ex.InnerException.Message);
        Console.WriteLine("Stack:\n" + ex.StackTrace);
    }
    
}
j3270
  • 1
  • 2

1 Answers1

0

I realized my mistake. I wasn't authenticating the new HttpClient.

Earlier in the example the 'Microsoft.VisualStudio.Services.WebApi.VssConnection' was authenticated with our PAT and was used to get a BuildHttpClient to work with. That client was what I used to get the download URL.

The new HttpClient isn't authenticated in the example. However, I kept digging and looked at the REST API offered by MS and they show how to authenticate an HttpClient with a PAT in this example getting a list of projects

  public static async void GetProjects()
  {
   try
   {
    var personalaccesstoken = "PAT_FROM_WEBSITE";
  
    using (HttpClient client = new HttpClient())
    {
     client.DefaultRequestHeaders.Accept.Add(
      new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
  
     client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
      Convert.ToBase64String(
       System.Text.ASCIIEncoding.ASCII.GetBytes(
        string.Format("{0}:{1}", "", personalaccesstoken))));
  
     using (HttpResponseMessage response = await client.GetAsync(
        "https://dev.azure.com/{organization}/_apis/projects"))
     {
      response.EnsureSuccessStatusCode();
      string responseBody = await response.Content.ReadAsStringAsync();
      Console.WriteLine(responseBody);
     }
    }
   }
   catch (Exception ex)
   {
    Console.WriteLine(ex.ToString());
   }
  }

After doing that in my function above, my downloads succeeded.

The response was succeeding with a 203 vs 200 code previously.. Should have been my first clue. Now I know.

j3270
  • 1
  • 2