Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Download release assets #2918

Open
nicola-lunghi opened this issue Mar 12, 2024 · 12 comments · May be fixed by #3060
Open

Download release assets #2918

nicola-lunghi opened this issue Mar 12, 2024 · 12 comments · May be fixed by #3060

Comments

@nicola-lunghi
Copy link

The documentation says that I can download a release assets with:

To download the asset's binary content, set the Accept header of the request to [application/octet-stream](https://docs.github.com/rest/overview/media-types). The API will either redirect the client to the location, or stream it directly if possible. API clients should handle both a 200 or 302 response.

Can I do it with this library?

@xvega
Copy link
Contributor

xvega commented Mar 12, 2024

The documentation says that I can download a release assets with:

To download the asset's binary content, set the Accept header of the request to [application/octet-stream](https://docs.github.com/rest/overview/media-types). The API will either redirect the client to the location, or stream it directly if possible. API clients should handle both a 200 or 302 response.

Can I do it with this library?

I don't think this library provides a direct method to download assets, but you could use the asset's URL with a HTTP library like requests to download the asset.

def browser_download_url(self) -> str:

This is an idea/pseudocode that might help you get started (haven't tested this)

from github import Github
import requests

g = Github("your token")
repo = g.get_repo("your repo")

# Get the specific release or terate over releases
release = repo.get_release("tag_name")

# Loop through assets in the release
for asset in release.get_assets():
    response = requests.get(asset.browser_download_url, allow_redirects=True)
    # whatever you need to do with the binary 

@nicola-lunghi
Copy link
Author

nicola-lunghi commented Mar 12, 2024 via email

@nicola-lunghi
Copy link
Author

nicola-lunghi commented Mar 12, 2024 via email

@nicola-lunghi
Copy link
Author

nicola-lunghi commented Mar 28, 2024

Hi @EnricoMi if I submit a PR would you accept this? there's a good reason why this is not included? there's a similar API also for downloading job artifacts.
Also where I can add this functionality?

    request_url = f"{__gh_base_url__}/repos/{artifact_data['repo_name']}/releases/assets/{artifact_data['id']}"
    headers = {
        "Accept": "application/octet-stream",
        "Authorization": f"Bearer {token}",
    }

    with open(destfile, "wb") as f:
        r = requests.get(request_url, headers=headers, stream=True, timeout=5)
        total_length = r.headers.get("content-length")

        if total_length is None:  # no content length header
            f.write(r.content)
        else:
            for chunk in r.iter_content(chunk_size=4096):
                f.write(chunk)

the missing functionality is to be able to set this header

      "Accept": "application/octet-stream",

@neel-m
Copy link

neel-m commented Oct 9, 2024

There is some history:
#1541
#2445

There was a pull request:
#2624

While the browser_download_url might work for a public repository, it definitely won't for a private repo which needs proper authentication headers.

@EnricoMi
Copy link
Collaborator

EnricoMi commented Oct 9, 2024

@nicola-lunghi yes, please, go ahead!

@neel-m
Copy link

neel-m commented Oct 9, 2024

I had a local change for download_asset and requestFile that worked on code from a year or so ago. I can clean it up and submit a PR, if someone will look at it.

@EnricoMi
Copy link
Collaborator

EnricoMi commented Oct 9, 2024

Will do.

@neel-m
Copy link

neel-m commented Oct 9, 2024

Looks like there have been some changes to the repo, so will need to refactor my change to work with the changed code.

@neel-m
Copy link

neel-m commented Oct 10, 2024

First draft is ready here: #3060

@EnricoMi EnricoMi linked a pull request Oct 11, 2024 that will close this issue
@neel-m
Copy link

neel-m commented Oct 15, 2024

Any comments on the PR?
What is the process for review?
It looks like the project is anti- https://www.conventionalcommits.org/en/v1.0.0/ if so, it would be good to put that in the contribution guide.

@mickem
Copy link

mickem commented Jan 8, 2025

If someone is looking for a quick workaround for private repositories, this is what I came up with.
It uses PyGitHub to fetch the link which is then using whatever authentication you have provided and then requests to actually fetch the unauthenticated link produced in the previous call.

def download_asset(asset: GitReleaseAsset) -> str:
    """Download a release asset.

    Args:
        asset: The release asset to download.

    """
    headers = {"Accept": "application/octet-stream"}
    (status, headers, _) = asset.requester.requestBlob("GET", asset.url, headers=headers)
    if status != 302:
        msg = f"Download failed expected 302 got {status}"
        raise Exception(msg)
    response = requests.get(headers["location"])
    if response.status_code != 200:
        msg = f"Download failed expected 200 got {response.status_code}"
        raise Exception(msg)
    return response.text

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants