Ramakrishna Reddy
Ramakrishna Reddy

Reputation: 347

Read image from private GitHub repository programmatically using C#

Need to store the image from a private git repository to a blob using C#. Tried with below code but getting 404 errors.

I am using the below code from C# example of downloading GitHub private repo programmatically

var githubToken = "[token]";
var url = 
"https://github.com/[username]/[repository]/archive/[sha1|tag].zip";
var path = @"[local path]";

using (var client = new System.Net.Http.HttpClient())
{
var credentials = string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0}:", githubToken);
credentials = Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes(credentials));
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", credentials);
var contents = client.GetByteArrayAsync(url).Result;
System.IO.File.WriteAllBytes(path, contents);
}

Note: Able to fetch from the public repository

Upvotes: 0

Views: 1657

Answers (2)

itminus
itminus

Reputation: 25360

How to fix :

  1. The URL is changed to GET /repos/:owner/:repo/:archive_format/:ref. See https://developer.github.com/v3/repos/contents/#get-archive-link

    For private repositories, these links are temporary and expire after five minutes.

    GET /repos/:owner/:repo/:archive_format/:ref

  2. You should not pass the credentials using basic authentication. Instead, you should create a token by following the official docs. see https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line

  3. Finally, you need pass an extra User-Agent header. It is required by GitHub API. See https://developer.github.com/v3/#user-agent-required :

    All API requests MUST include a valid User-Agent header.

Demo

public class GitHubRepoApi{

    public string EndPoint {get;} = "https://api.github.com/repos";

    public async Task DownloadArchieveAsync(string saveAs, string owner, string token, string repo,string @ref="master",string format="zipball")
    {
        var url = this.GetArchieveUrl(owner, repo, @ref, format);
        var req = this.BuildRequestMessage(url,token);
        using( var httpClient = new HttpClient()){
            var resp = await httpClient.SendAsync(req);
            if(resp.StatusCode != System.Net.HttpStatusCode.OK){
                throw new Exception($"error happens when downloading the {req.RequestUri}, statusCode={resp.StatusCode}");
            }
            using(var fs = File.OpenWrite(saveAs) ){
                await resp.Content.CopyToAsync(fs);
            }
        }
    }
    private string GetArchieveUrl(string owner, string repo, string @ref = "master", string format="zipball")
    {
        return $"{this.EndPoint}/{owner}/{repo}/{format}/{@ref}"; // See https://developer.github.com/v3/repos/contents/#get-archive-link
    }
    private HttpRequestMessage BuildRequestMessage(string url, string token)
    {
        var uriBuilder = new UriBuilder(url);
        uriBuilder.Query = $"access_token={token}";   // See https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line
        var req = new HttpRequestMessage();
        req.RequestUri = uriBuilder.Uri;
        req.Headers.Add("User-Agent","My C# Client"); // required, See https://developer.github.com/v3/#user-agent-required
        return req;
    }
}

Test :

var api = new GitHubRepoApi();
var saveAs= Path.Combine(Directory.GetCurrentDirectory(),"abc.zip");
var owner = "newbienewbie";
var token = "------your-----token--------";
var repo = "your-repo";
var @ref = "6883a92222759d574a724b5b8952bc475f580fe0"; // will be "master" by default
api.DownloadArchieveAsync(saveAs, owner,token,repo,@ref).Wait();

Upvotes: 2

Jim Xu
Jim Xu

Reputation: 23121

According to the message you provide, you use the wrong url to download. Regarding how to get the download url, please refer to the following steps:

  1. Use the following url to get the download url
Method: GET
URL: https://api.github.com/repos/:owner/:repo/contents/:path?ref:<The name of the commit/branch/tag>
Header:
       Authorization: token <personal access token>

The repose body will tell you the download url For example : enter image description here

  1. Download file enter image description here

For more details, please refer to https://developer.github.com/v3/repos/contents/#get-contents.

Upvotes: 1

Related Questions