通过 GitLab API 下载已手动上传的文件

Download files through GitLab API that has been manually uploaded

我们有一个自托管的 GitLab 服务器,并且正在致力于自动化我们的构建和发布。我们有许多在使用 GitLab CI 之前构建的旧版本。其中一些应该包含在某个软件的发布包中。这些版本并不位于任何易于访问的服务器上,因此如果可以从我们的 GitLab 服务器访问它们将非常容易。

可以从 API 访问标签并从构建作业中获取工件。似乎无法手动添加构建工件,因此无法将其用于旧版本。

可以将文件上传到标签的发行说明。这些通过网页下载非常简单,但我找不到任何通过API下载这些的方法。有这个 API 端点:

https://docs.gitlab.com/ee/api/projects.html#upload-a-file

但是没有"download-a-file".

有没有一种简单的方法可以将文件上传到我们自托管的 GitLab,然后通过 API 下载它们?

我们所有的存储库都将可见性设置为私有。如果您尝试在未登录的情况下访问像这样的 link:

http://www.example.com/group/my-project/uploads/443568a8641b1b48fc983daea27d36c0/myfile.zip

然后您将被重定向到登录页面。

无法从 GitLab API 下载文件。这是 GitLab 跟踪此功能的问题:

https://gitlab.com/gitlab-org/gitlab/issues/25838

------

作为目前的解决方法,我使用 python 脚本来简单地登录页面并获取文件。这需要用户的用户名和密码。我设置了一个新用户,它只能在需要的地方访问特定的项目,所以在这个项目的构建脚本中使用它应该足够安全。

import argparse
import sys
import mechanize

def login_and_download(url, user, password):
    br = mechanize.Browser()
    br.set_handle_robots(False)
    br.open(url)
    br.select_form(id = 'new_user')
    br['user[login]'] = user
    br['user[password]'] = password
    response = br.submit()
    filename = url.split('/')[-1] #Last part of url
    with open(filename, 'wb') as f:
        f.write(response.get_data())

def main():
    parser = argparse.ArgumentParser(description = 'Downloads files from a private git repo')
    parser.add_argument('url',  help = 'The URL to download')
    parser.add_argument('user',  help = 'The username to use')
    parser.add_argument('password',  help = 'The password to use')
    args = parser.parse_args()

    if len(sys.argv) == 1:
        parser.print_help()
        sys.exit(1)

    login_and_download(args.url, args.user, args.password)

if __name__ == '__main__':
    main()

这是 python 脚本的另一个示例,仍然来自 issue 25838

它翻译 curl 调用:

curl --request GET 'http://127.0.0.1:3000/root/my-project/uploads/d3d527ac296ae1b636434f44c7f57272/IMG_3935.jpg' \
     --header 'Authorization: Bearer YOUR_API_TOKEN'
import requests
from bs4 import BeautifulSoup

with requests.Session() as http_session:

    # my login page url
    login_url = [LOGIN_URL]
    login_page = http_session.get(login_url)
    login_inputs = BeautifulSoup(login_page.content, features='html.parser').find_all('input')

    # get the authenticity token from the login page
    for login_input in login_inputs:
        if 'token' in login_input['name']:
            auth_token = login_input['value']
            break

    # send some user-agent header just in case
    headers = {"User-Agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"}

    # see your login page source for the required data ...
    data = {
        "username": [MYUSERNAME],
        "password": [MYPASSWORD],
        "authenticity_token": auth_token,
        "remember_me": "1",
        "commit": "Sign in"
    }

    # ... as well as the login endpoint
    login_endpoint = [LOGIN_ENDPOINT_URL]

    # authenticate
    http_session.post(login_endpoint, data=data, headers=headers)

    # myfile_url is the url for my wanted file
    myfiledata = http_session.get(myfile_url).content