新聞中心
現(xiàn)在是時(shí)候?qū)懸黄恼铝?,這樣以后我和其他人就都不必在一個(gè)簡(jiǎn)單的問(wèn)題上花費(fèi)太多時(shí)間了。

在本文中,我將向您展示如何使用 GitHub API 獲取大于 1MB 的文件。學(xué)習(xí)完本文章后,您將會(huì)了解以下內(nèi)容:
- 如何使用 GitHub API 獲取大文件
- 如何使用commit SHA
- 使用 blob 和 base64 編碼數(shù)據(jù)
在本文中,我將使用了來(lái)自 HackerNoon 的年度創(chuàng)業(yè)大賽(https://startups.hackernoon.com/faq?ref=hackernoon.com)的數(shù)據(jù)。 該部分?jǐn)?shù)據(jù)在 GitHub上是公開(kāi)的。
獲取小于1MB的文件
獲取較小的文件很簡(jiǎn)單,您只需將三個(gè)參數(shù)傳遞給 API。 首先是所有者的姓名,可以是您的用戶名。第二個(gè)是 repo,它是提交文件的存儲(chǔ)庫(kù)。path 是文件的絕對(duì)路徑。
下面是我使用codepen創(chuàng)建的一小段代碼,供大家參考。
let fileSHA, fileBlob, fileContent, file
const getFileSHA = async () => {
try {
const response = await fetch(
"https://api.github.com/repos/hackernoon/where-startups-trend/contents/2021/"
);
const data = await response.json();
// console.log(data);
fileSHA = data[1].sha
console.log(fileSHA);
} catch (error) {
console.log(error);
}
getFileBlob()
}
const getFileBlob = async (fileSHA)=> {
try {
const response = await fetch(
`https://api.github.com/repos/hackernoon/where-startups-trend/git/blobs/a51a49dfc2bd7be262bd59bb85e85271ea0c18cd`
);
const data = await response.json();
fileBlob = data.content
convertBlob(fileBlob)
} catch (error) {
console.log(error);
}
}
const convertBlob = async blob => {
// console.log(blob)
try {
// const fileContents = Buffer.from(blob, "base64").toString()
// file = JSON.parse(fileContents)
// file = JSON.parse(fileContents)
fileContents = base64EncodeUnicode(blob)
file = JSON.parse(fileContents)
console.log(file)
} catch(error) {
console.log(error)
}
}
function base64EncodeUnicode(str) {
utf8Bytes = decodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
return String.fromCharCode('0x' + p1);
});
return atob(utf8Bytes);
}
getFileSHA()
為了更好地理解上述代碼,我創(chuàng)建了四個(gè)變量,用來(lái)存儲(chǔ)不同狀態(tài)下的數(shù)據(jù)。
let fileSHA, fileBlob, fileContent, file
- fileSHA用來(lái)存儲(chǔ)我們想要獲取的文件的 SHA
- fileBlob存儲(chǔ)從API 獲取的 blob。
- fileContent用于存儲(chǔ)解碼后的字符串。
- file包含我們真正需要的數(shù)據(jù)。
您可以在下一節(jié)中找到對(duì)應(yīng)的參考代碼,只需將文件夾路徑更改為實(shí)際文件路徑(帶文件擴(kuò)展名)。
獲取大文件
但是,如果您需要獲取大于 1MB 的文件,API 會(huì)拋出錯(cuò)誤。這是因?yàn)樯鲜龇绞讲恢С执笪募?。若需要獲取大文件,我們必須改為使用 Github API。
這類API允許您從 Git 存儲(chǔ)庫(kù)和列表中讀取和寫入原始 Git 對(duì)象,也可以更新 Git 引用(Git references)。 該類API主要適用于blob,這正是本文的重點(diǎn)。
Git將大文件轉(zhuǎn)換為base64 編碼的 blob,而不是存儲(chǔ)整個(gè)文件,以便獲得更好的性能。因此,當(dāng)您請(qǐng)求同一個(gè)文件時(shí),希望您使用返回 blob的接口。
要獲取blob,您需要傳遞文件對(duì)應(yīng)的SHA。您可能想問(wèn),什么是 SHA?又該如何獲得它?
每次提交新文件時(shí),git 都會(huì)創(chuàng)建一個(gè)名為 hash 或 SHA 的唯一ID 來(lái)記錄此次更改。但有時(shí)可能會(huì)導(dǎo)致問(wèn)題,我將在本文末尾討論這個(gè)問(wèn)題。
獲取文件對(duì)應(yīng)的SHA
現(xiàn)在,我們需要找到一種方法來(lái)獲取所需文件的“SHA”。GitHub API有一個(gè)接口,可以用來(lái)同我們需要使用的文件內(nèi)容進(jìn)行交互。
GET /repos/{owner}/{repo}/contents/{path}
作為響應(yīng),我們得到一個(gè)有關(guān)對(duì)象的數(shù)組,其中包含目錄中每個(gè)文件的元數(shù)據(jù)。 元數(shù)據(jù)中包含我們可以存儲(chǔ)和后面會(huì)用到的SHA。
const getFileSHA = async () => {
try {
const response = await fetch(
" "
);
const data = await response.json();
console.log(data);
fileSHA = data[3].sha
console.log(fileSHA);
} catch (error) {
console.log(error);
}
getFileBlob(fileSHA)
}
data[3].sha 是具有 votes_by_region.jso n 的 SHA,因此我們將其存儲(chǔ)在 fileSHA 中以備后面使用。 下圖是控制臺(tái)的輸出情況:
獲取對(duì)應(yīng)的Blob
我們已經(jīng)獲取了blob所需SHA。 我們需要使用不同的接口來(lái)處理 blob。 這個(gè)接口與上一個(gè)接口相似,但該接口需要將文件對(duì)應(yīng)的SHA 作為第三個(gè)參數(shù)傳遞。
GET /repos/{owner}/{repo}/git/blobs/{file_sha}
當(dāng)我們向下面的函數(shù)提供文件的 SHA 作為參數(shù)時(shí),就可以獲取對(duì)應(yīng)blob。
const getFileBlob = async (fileSHA)=> {
try {
const response = await fetch(
`https://api.github.com/repos/hackernoon/where-startups-trend/git/blobs/${fileSHA}`
);
const data = await response.json();
fileBlob = data.content
convertBlob(fileBlob)
} catch (error) {
console.log(error);
}
}
此請(qǐng)求返回一個(gè) base64 編碼的 blob。 Base64 是一種以 ASCII 字符串格式表示二進(jìn)制數(shù)據(jù)的編碼方案。 當(dāng)我們需要在不進(jìn)行任何修改的情況下存儲(chǔ)或傳輸數(shù)據(jù)時(shí),它很有用。控制臺(tái)輸出看起來(lái)很亂,但這就是 base64 編碼數(shù)據(jù)的方式。
將 Blob 轉(zhuǎn)換為可使用的數(shù)據(jù)
在最后一步,我們需要將以 base64 編碼的 blob 轉(zhuǎn)換為我們可以在程序中使用的數(shù)據(jù)。 但這一步非常令人沮喪,因?yàn)闃?biāo)準(zhǔn)方法在某些情況下似乎不起作用。在這個(gè)問(wèn)題上花了幾個(gè)小時(shí)后,我找到了三個(gè)解決方案。
1.最簡(jiǎn)單的方法
這是 JavaScript 原生支持的標(biāo)準(zhǔn)方式。 atob() 是一個(gè) Web API 接口,可將 base64 編碼數(shù)據(jù)解碼為純字符串。
atob 把讀取的 ASCII 轉(zhuǎn)化為二進(jìn)制,因?yàn)樗鼘⒁?ASCII 編碼的 base64 數(shù)據(jù)轉(zhuǎn)換為二進(jìn)制形式。 輸出將是一個(gè)解碼后的字符串。 要將其轉(zhuǎn)換為其原始數(shù)據(jù)類型,我們使用 JSON.parse()。
fileContents = atob(blob)
file = JSON.parse(fileContents)
2.第二種方法
如果上述方法拋出錯(cuò)誤,你可以使用Node.js 提供了一個(gè)方法 Buffer.from()。 它將要解碼的字符串作為第一個(gè)參數(shù),將編碼技術(shù)作為第二個(gè)參數(shù)。
try {
const fileContents = Buffer.from(fileBlob, "base64").toString()
file = JSON.parse(blobToString)
console.log(file)
} catch(error) {
console.log(error)
}
3.第三種方法
如果您在前端工作,則前面提到的方法很有可能不起作用。 在這種情況下,創(chuàng)建一個(gè)使用 decodeURIComponent 的函數(shù)。
// define the function
const decodeBase64 = str => {
utf8Bytes = decodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
return String.fromCharCode('0x' + p1);
});
return atob(utf8Bytes);
}
您可以通過(guò)傳遞 fileBlob 作為參數(shù)來(lái)調(diào)用此函數(shù),并獲取您需要的解碼字符串。
fileContents = decodeBase64(fileBlob)
file = JSON.parse(fileContents)
console.log(file)
依然不能正常工作
此時(shí),您可以嘗試兩種最終選擇。您可以使用 FileReader API 或以不同的方式使用 decodeURIComponent。
1.FileReader API:您可以在此處找到 MDN 文檔(https://developer.mozilla.org/en-US/docs/Web/API/FileReader?ref=hackernoon.com)
2.decodeURIComponent:請(qǐng)參閱 Rajeev Singh關(guān)于處理 16 位編碼字符串的博客。(https://www.base64decoder.io/javascript/?ref=hackernoon.com)
或者,您也可以嘗試一個(gè)名為 js-base64(https://www.npmjs.com/package/js-base64?ref=hackernoon.com)的 NPM 包。我自己沒(méi)有使用過(guò),所以無(wú)法提供建設(shè)性的意見(jiàn)。
注意
如前所述,SHA 是在每次修改文件時(shí)都會(huì)更改的具有唯一性的ID號(hào)。此外,由于我們?cè)?getFileSHA() 函數(shù)中有一個(gè)硬編碼的對(duì)象索引,如果您在目錄中添加或刪除文件,API 可能會(huì)以不同文件的 SHA 響應(yīng)。
為了解決這個(gè)問(wèn)題,您可以明確指明的文件名而不是索引,這樣您就可以在提交新更改后保持函數(shù)不變。
總結(jié)和 TL;DR
1.Git 以 blob 格式存儲(chǔ)較大的文件,因此我們使用 GitHub 數(shù)據(jù)庫(kù) API 來(lái)獲取大于 1MB 的文件。
2.我們需要提供用戶名、repo 名稱和文件的 SHA 來(lái)獲取 blob。
3.為了獲取 SHA,我們需要向接口提供文件夾路徑并將其存儲(chǔ)在變量中。
4.之后我們需要將 SHA 作為參數(shù)傳遞給另一個(gè)接口并獲得一個(gè) base64 編碼的 blob。
5.必須將 blob 解碼為純字符串,然后使用 JSON.parse() 將其轉(zhuǎn)換為原始格式,然后才能使用它。
更多參考資料
GitHub 存儲(chǔ)庫(kù)的內(nèi)容(https://docs.github.com/en/rest/reference/repos?ref=hackernoon.com#contents)
Git 數(shù)據(jù)庫(kù)(https://docs.github.com/en/rest/reference/git?ref=hackernoon.com)
Git 數(shù)據(jù)庫(kù) API 入門(https://docs.github.com/en/rest/guides/getting-started-with-the-git-database-api?ref=hackernoon.com)
譯者介紹
趙青窕,社區(qū)編輯,從事多年驅(qū)動(dòng)開(kāi)發(fā)。研究興趣包含安全OS和網(wǎng)絡(luò)安全領(lǐng)域,發(fā)表過(guò)網(wǎng)絡(luò)相關(guān)專利。
原文標(biāo)題:??How to Fetch Large Data Files Through GitHub API??,作者:Kaushal Joshi
網(wǎng)站名稱:如何通過(guò)GitHubAPI獲取較大的文件
新聞來(lái)源:http://www.5511xx.com/article/coeiicp.html


咨詢
建站咨詢
