使用 node.js 从私人存储库下载 zip 版本
Download zip release from private repository with node.js
我正在尝试从私人存储库下载 zip 版本,我尝试了很多解决方案,但 none 似乎有效。
这是我的代码:
function Download(url, path, options) {
updateHeader(options.stageTitles.Downloading)
let received_bytes = 0;
let total_bytes = 0;
// eslint-disable-next-line
console.log('-----------------')
// eslint-disable-next-line
console.log(url, path)
console.log('-----------------')
var req = request(
{
method: 'GET',
uri: url,
headers: {
Authorization: `token ${options.gitRepoToken}`,
'Accept': 'application/octet-stream',
'User-Agent': 'request module',
},
//encoding: null
}
);
// eslint-disable-next-line
console.log(req)
var out = fs.createWriteStream(path);
req.pipe(out);
req.on('response', data => {
// eslint-disable-next-line
console.log(data.headers, data)
total_bytes = parseInt(data.headers['content-length']);
});
req.on('data', chunk => {
received_bytes += chunk.length;
showProgress(received_bytes, total_bytes);
});
req.on('end', () => {
Install(options)
});}
url 变量等于:https://github.com/SolberLight/PRIVATE_REPO_NAME/releases/download/1.0/MY_ZIP_NAME.zip
看起来我总是得到 9 字节的内容大小和“未找到”响应所以我猜我的 headers 不正确?
感谢您的帮助!
编辑 1:
取得了一些进展,但现在看来 blob 的大小不正确
(async () => {
//get latest release
var response = await axios.get(
`https://api.github.com/repos/${repoWithOwner}/releases/latest`,
{
headers: authHeaders,
}
);
var assets = response.data.assets;
for (var i = 0; i < assets.length; i++) {
console.log(assets[i].url);
response = await axios({
method: "get",
url: assets[i].url,
responseType: "blob",
headers: {
//Accept: "application/octet-stream",
...authHeaders,
},
});
// eslint-disable-next-line
console.log(response.data, path)
let reader = new FileReader()
reader.onload = function() {
if (reader.readyState == 2) {
var buffer = new Buffer(reader.result)
console.log(`Saving ${JSON.stringify({ fileName: 'myfile.zip', size: response.data.size })}`)
outputFile(path, buffer, err => {
if (err) {
// eslint-disable-next-line
console.log(err.message)
} else {
// eslint-disable-next-line
console.log(path)
}
})
}
}
reader.readAsArrayBuffer(response.data)
}
})();
您可以使用下载存储库存档 (zip) 端点,已记录 here
考虑以下因素:
您将向 /repos/{owner}/{repo}/zipball/{ref} 执行 GET 请求
第一个请求会发送重定向(302响应),您需要正确地遵循重定向,在这种情况下,由于您使用的是axios,因此您需要手动处理。响应将包含您将在以下请求中使用的 zipball_url。
由于您下载的是私人回购版本,请考虑到这些链接是临时的,会在五分钟后过期。
第一个请求接受用户或安装令牌(以防您将 API 作为 GitHub 应用程序使用)。详细了解 GitHub 应用程序和 GitHub OAuth 应用程序之间的区别 here
如果您使用的是 GitHub OAuth 应用程序,请确保您拥有 repo scope, for GitHub Application, ensure you have the Contents permissions
查看以下工作示例:
Download a zip release from GitHub
View in Fusebit
const owner = 'stack-overflow-demos';
// For the purpose of this example, we have 1 release, so it will be always the first item.
const releases = await installationClient.rest.repos.listReleases({
owner: 'stack-overflow-demos',
repo: 'private-demo'
});
// Get release information (e.g zipball URL)
const release = await installationClient.rest.repos.getRelease({
owner: 'stack-overflow-demos',
repo: 'private-demo',
release_id: releases.data[0].id,
});
const { token } = await installationClient.auth();
// According to official GitHub docs https://docs.github.com/en/rest/reference/repos#download-a-repository-archive-zip
// You will get a zipball URL you can use to download the zip file, you need to handle properly the redirects since a second GET
// request is needed, this time with an authenticated URL.
const { zipball_url, tag_name } = release.data;
const response = await getZipFile(zipball_url, token);
// Handle redirects properly if a responseUrl is returned that means you need to perform the redirect,
// you don't need to send the access token to this request, since is a signed URL
// Note: For private repositories, these links are temporary and expire after five minutes.
const {
request: {
res: { responseUrl },
},
} = response;
if (responseUrl) {
await downloadZipFile(responseUrl, `/tmp/'${tag_name}.zip`);
}
// Get information about the zip file you're about to download
const getZipFile = async (url, token) => {
return await axios({
redirect: 'manual',
method: 'get',
url,
headers: {
Authorization: `token ${token}`,
Accept: 'application/vnd.github.v3+json',
},
});
};
// Download the zip file from the temporary secure URL returned from the first request
const downloadZipFile = async (url, filePath) => {
const response = await axios({
method: 'get',
url,
responseType: 'stream',
headers: {
Accept: 'application/octet-stream',
},
});
return new Promise((resolve, reject) => {
console.log(`writing to ${filePath}`);
const dest = fs.createWriteStream(filePath);
let progress = 0;
response.data
.on('end', () => {
console.log(' Done downloading file.');
resolve(filePath);
})
.on('error', (err) => {
console.error(' Error downloading file.');
reject(err);
})
.on('data', (d) => {
progress += d.length;
console.log(` Downloaded ${progress} bytes`);
})
.pipe(dest);
});
};
这个例子使用的是Octokit
我正在尝试从私人存储库下载 zip 版本,我尝试了很多解决方案,但 none 似乎有效。
这是我的代码:
function Download(url, path, options) {
updateHeader(options.stageTitles.Downloading)
let received_bytes = 0;
let total_bytes = 0;
// eslint-disable-next-line
console.log('-----------------')
// eslint-disable-next-line
console.log(url, path)
console.log('-----------------')
var req = request(
{
method: 'GET',
uri: url,
headers: {
Authorization: `token ${options.gitRepoToken}`,
'Accept': 'application/octet-stream',
'User-Agent': 'request module',
},
//encoding: null
}
);
// eslint-disable-next-line
console.log(req)
var out = fs.createWriteStream(path);
req.pipe(out);
req.on('response', data => {
// eslint-disable-next-line
console.log(data.headers, data)
total_bytes = parseInt(data.headers['content-length']);
});
req.on('data', chunk => {
received_bytes += chunk.length;
showProgress(received_bytes, total_bytes);
});
req.on('end', () => {
Install(options)
});}
url 变量等于:https://github.com/SolberLight/PRIVATE_REPO_NAME/releases/download/1.0/MY_ZIP_NAME.zip
看起来我总是得到 9 字节的内容大小和“未找到”响应所以我猜我的 headers 不正确?
感谢您的帮助!
编辑 1: 取得了一些进展,但现在看来 blob 的大小不正确
(async () => {
//get latest release
var response = await axios.get(
`https://api.github.com/repos/${repoWithOwner}/releases/latest`,
{
headers: authHeaders,
}
);
var assets = response.data.assets;
for (var i = 0; i < assets.length; i++) {
console.log(assets[i].url);
response = await axios({
method: "get",
url: assets[i].url,
responseType: "blob",
headers: {
//Accept: "application/octet-stream",
...authHeaders,
},
});
// eslint-disable-next-line
console.log(response.data, path)
let reader = new FileReader()
reader.onload = function() {
if (reader.readyState == 2) {
var buffer = new Buffer(reader.result)
console.log(`Saving ${JSON.stringify({ fileName: 'myfile.zip', size: response.data.size })}`)
outputFile(path, buffer, err => {
if (err) {
// eslint-disable-next-line
console.log(err.message)
} else {
// eslint-disable-next-line
console.log(path)
}
})
}
}
reader.readAsArrayBuffer(response.data)
}
})();
您可以使用下载存储库存档 (zip) 端点,已记录 here
考虑以下因素:
您将向 /repos/{owner}/{repo}/zipball/{ref} 执行 GET 请求
第一个请求会发送重定向(302响应),您需要正确地遵循重定向,在这种情况下,由于您使用的是axios,因此您需要手动处理。响应将包含您将在以下请求中使用的 zipball_url。
由于您下载的是私人回购版本,请考虑到这些链接是临时的,会在五分钟后过期。
第一个请求接受用户或安装令牌(以防您将 API 作为 GitHub 应用程序使用)。详细了解 GitHub 应用程序和 GitHub OAuth 应用程序之间的区别 here
如果您使用的是 GitHub OAuth 应用程序,请确保您拥有 repo scope, for GitHub Application, ensure you have the Contents permissions
查看以下工作示例:
Download a zip release from GitHub | View in Fusebit |
---|
const owner = 'stack-overflow-demos';
// For the purpose of this example, we have 1 release, so it will be always the first item.
const releases = await installationClient.rest.repos.listReleases({
owner: 'stack-overflow-demos',
repo: 'private-demo'
});
// Get release information (e.g zipball URL)
const release = await installationClient.rest.repos.getRelease({
owner: 'stack-overflow-demos',
repo: 'private-demo',
release_id: releases.data[0].id,
});
const { token } = await installationClient.auth();
// According to official GitHub docs https://docs.github.com/en/rest/reference/repos#download-a-repository-archive-zip
// You will get a zipball URL you can use to download the zip file, you need to handle properly the redirects since a second GET
// request is needed, this time with an authenticated URL.
const { zipball_url, tag_name } = release.data;
const response = await getZipFile(zipball_url, token);
// Handle redirects properly if a responseUrl is returned that means you need to perform the redirect,
// you don't need to send the access token to this request, since is a signed URL
// Note: For private repositories, these links are temporary and expire after five minutes.
const {
request: {
res: { responseUrl },
},
} = response;
if (responseUrl) {
await downloadZipFile(responseUrl, `/tmp/'${tag_name}.zip`);
}
// Get information about the zip file you're about to download
const getZipFile = async (url, token) => {
return await axios({
redirect: 'manual',
method: 'get',
url,
headers: {
Authorization: `token ${token}`,
Accept: 'application/vnd.github.v3+json',
},
});
};
// Download the zip file from the temporary secure URL returned from the first request
const downloadZipFile = async (url, filePath) => {
const response = await axios({
method: 'get',
url,
responseType: 'stream',
headers: {
Accept: 'application/octet-stream',
},
});
return new Promise((resolve, reject) => {
console.log(`writing to ${filePath}`);
const dest = fs.createWriteStream(filePath);
let progress = 0;
response.data
.on('end', () => {
console.log(' Done downloading file.');
resolve(filePath);
})
.on('error', (err) => {
console.error(' Error downloading file.');
reject(err);
})
.on('data', (d) => {
progress += d.length;
console.log(` Downloaded ${progress} bytes`);
})
.pipe(dest);
});
};
这个例子使用的是Octokit