How to upload a file using GitHub API

Maybe it’s just me, but this guide https://developer.github.com/v3/repos/contents/ is incredibly vague.
Simple examples would be handy, and not so much emphasis on what the return messages.

The objective is to upload a file, preferably .pdf or .png through a curl command.
Any help/pointers will be highly appreciated.

1 Like

It’s hard to write documentation that is both approachable but also has a good amount of detail to answer whatever questions that people will have.

So you’re going to need to understand a few things about the information in the create a file endpoint reference:

  • You’re going to need to be authenticated and have write permissions on the repository
  • You need to pass certain things in the URL and others in the body of the HTTP request
    • Replaceable parameters in the URL start with a colon :

I’m also going to be using HTTPie instead of curl because it makes JSON REST API interactions much easier. (And I was never very good at using curl for things :grinning:)

I used the following command:

http PUT https://api.github.com/repos/lee-dohm/test-repo/contents/hello.txt \
  "Authorization: token REDACTED-TOKEN" \
  message="my commit message" \
  committer:="{ \"name\": \"Lee Dohm\", \"email\": \"1038121+lee-dohm@users.noreply.github.com\" }" \
  content="bXkgbmV3IGZpbGUgY29udGVudHM="

which resulted in the response:

{
  "commit": {
    "author": {
      "date": "2019-05-28T23:10:17Z",
      "email": "1038121+lee-dohm@users.noreply.github.com",
      "name": "Lee Dohm"
    },
    "committer": {
      "date": "2019-05-28T23:10:17Z",
      "email": "1038121+lee-dohm@users.noreply.github.com",
      "name": "Lee Dohm"
    },
    "html_url": "https://github.com/lee-dohm/test-repo/commit/76c36cec967c4d647422cf41982829d153fa8cce",
    "message": "my commit message",
    "node_id": "MDY6Q29tbWl0MTEyMTM3MDU2Ojc2YzM2Y2VjOTY3YzRkNjQ3NDIyY2Y0MTk4MjgyOWQxNTNmYThjY2U=",
    "parents": [
      {
        "html_url": "https://github.com/lee-dohm/test-repo/commit/d775caeeac9a48eb73f8012349c36a8c2b8c6e63",
        "sha": "d775caeeac9a48eb73f8012349c36a8c2b8c6e63",
        "url": "https://api.github.com/repos/lee-dohm/test-repo/git/commits/d775caeeac9a48eb73f8012349c36a8c2b8c6e63"
      }
    ],
    "sha": "76c36cec967c4d647422cf41982829d153fa8cce",
    "tree": {
      "sha": "1f3c23004c5252ee11cb723e3319d26d91bc19ac",
      "url": "https://api.github.com/repos/lee-dohm/test-repo/git/trees/1f3c23004c5252ee11cb723e3319d26d91bc19ac"
    },
    "url": "https://api.github.com/repos/lee-dohm/test-repo/git/commits/76c36cec967c4d647422cf41982829d153fa8cce",
    "verification": {
      "payload": null,
      "reason": "unsigned",
      "signature": null,
      "verified": false
    }
  },
  "content": {
    "_links": {
      "git": "https://api.github.com/repos/lee-dohm/test-repo/git/blobs/0d5a690c8fad5e605a6e8766295d9d459d65de42",
      "html": "https://github.com/lee-dohm/test-repo/blob/master/hello.txt",
      "self": "https://api.github.com/repos/lee-dohm/test-repo/contents/hello.txt?ref=master"
    },
    "download_url": "https://raw.githubusercontent.com/lee-dohm/test-repo/master/hello.txt",
    "git_url": "https://api.github.com/repos/lee-dohm/test-repo/git/blobs/0d5a690c8fad5e605a6e8766295d9d459d65de42",
    "html_url": "https://github.com/lee-dohm/test-repo/blob/master/hello.txt",
    "name": "hello.txt",
    "path": "hello.txt",
    "sha": "0d5a690c8fad5e605a6e8766295d9d459d65de42",
    "size": 20,
    "type": "file",
    "url": "https://api.github.com/repos/lee-dohm/test-repo/contents/hello.txt?ref=master"
  }
}

and generated this commit.

I hope that helps!

8 Likes

Maybe it will help to Someone:

<?php
$file_git = "wall.jpg";
$data_git = array(
'sha'=>file_get_contents("sha.txt"),
'message'=>'image',
'content'=> base64_encode($file_git),
'committer'=> array(
'name'=>'Jacob',
'email' => '45331093+greenandgreen@users.noreply.github.com'
)
);
$data_string_git = json_encode($data_git);
$ch_git = curl_init('https://api.github.com/repos/YOUR_REPO/contents/wall.jpg');
curl_setopt($ch_git, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($ch_git, CURLOPT_POSTFIELDS, $data_string_git);
curl_setopt($ch_git, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch_git, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 YaBrowser/19.9.3.314 Yowser/2.5 Safari/537.36',
'Authorization: token PLACE_YOUR_PERSONAL_TOKEN_HERE'
));
$result_git = curl_exec($ch_git);
echo $result_git;
$p_git = json_decode($result_git);
file_put_contents("sha.txt",$p_git->content->sha);
?>

Tested on PHP 7.
If the code is working, then I wouldn’t refuse likes, in gratitude for the little work :slight_smile:

7 Likes

what is 

'sha'=>file_get_contents("sha.txt")

To upload a new file do you still need it? My problem is that with HTTPFul i manage to put the zip file into github repo but the the file is corrupt, when i I do git pull and try to unzip the file it say unsupported format. and the size of the file is also just 4K. Here is my code 

$response = \Httpful\Request::put($url)  
 -\>addHeader('Authorization', "Basic $base64")  
 -\>addHeaders(  
array(  
'Accept-Encoding' =\> 'gzip, deflate',  
'Host' =\> 'api.github.com',  
'Cache-Control' =\> 'no-cache',  
'Accept' =\> '\*/\*',  
 )  
 )  
 -\>body('{  
 "message": "'.$commitMessage.'",  
 "content": "'.$sourceFile.'",  
 "branch":"'.$this-\>getSettings()-\>branch.'"  
 }')  
 -\> send();

Any help/suggestion will be appreciated thanks

Can anyone please show this using postman or Node.js .

1 Like

I’m trying to use the script above this comment but felt like commenting the solution to this problem since it was never listed. Basically, you have to get the sha from your existing file. In PHP, this is done using the sha1_file() method.

$shafile = "sha.txt";

// Put sha code into the file and close it.
$shatxtfile = fopen($shafile, "w") or die("Unable to open sha file!");
$sha = sha1_file("fakefilename.txt");
fwrite($shatxtfile, $sha);
fclose($shatxtfile);

For those looking for this solution, this is for a public folder and only sends the name of the file.

Also, the curl_init must specify the user, then the repository and, after contents, specify the file path.