UNPKG

@huggingface/hub

Version:

Utilities to interact with the Hugging Face hub

93 lines (80 loc) 2.51 kB
import { HUB_URL } from "../consts"; import { createApiError, InvalidApiResponseFormatError } from "../error"; import type { CredentialsParams, RepoDesignation } from "../types/public"; import { checkCredentials } from "../utils/checkCredentials"; import { toRepoId } from "../utils/toRepoId"; export interface FileDownloadInfoOutput { size: number; etag: string; /** * In case of LFS file, link to download directly from cloud provider */ downloadLink: string | null; } /** * @returns null when the file doesn't exist */ export async function fileDownloadInfo( params: { repo: RepoDesignation; path: string; revision?: string; hubUrl?: string; /** * Custom fetch function to use instead of the default one, for example to use a proxy or edit headers. */ fetch?: typeof fetch; /** * To get the raw pointer file behind a LFS file */ raw?: boolean; /** * To avoid the content-disposition header in the `downloadLink` for LFS files * * So that on browsers you can use the URL in an iframe for example */ noContentDisposition?: boolean; } & Partial<CredentialsParams> ): Promise<FileDownloadInfoOutput | null> { const accessToken = checkCredentials(params); const repoId = toRepoId(params.repo); const hubUrl = params.hubUrl ?? HUB_URL; const url = `${hubUrl}/${repoId.type === "model" ? "" : `${repoId.type}s/`}${repoId.name}/${ params.raw ? "raw" : "resolve" }/${encodeURIComponent(params.revision ?? "main")}/${params.path}` + (params.noContentDisposition ? "?noContentDisposition=1" : ""); const resp = await (params.fetch ?? fetch)(url, { method: "GET", headers: { ...(accessToken && { Authorization: `Bearer ${accessToken}`, }), Range: "bytes=0-0", }, }); if (resp.status === 404 && resp.headers.get("X-Error-Code") === "EntryNotFound") { return null; } if (!resp.ok) { throw await createApiError(resp); } const etag = resp.headers.get("ETag"); if (!etag) { throw new InvalidApiResponseFormatError("Expected ETag"); } const contentRangeHeader = resp.headers.get("content-range"); if (!contentRangeHeader) { throw new InvalidApiResponseFormatError("Expected size information"); } const [, parsedSize] = contentRangeHeader.split("/"); const size = parseInt(parsedSize); if (isNaN(size)) { throw new InvalidApiResponseFormatError("Invalid file size received"); } return { etag, size, downloadLink: new URL(resp.url).hostname !== new URL(hubUrl).hostname ? resp.url : null, }; }