Skip to content

下载 Tarball 示例

本页面展示如何使用 DownloadTarball 方法下载 NPM 包的 tarball 文件到本地。

下载流程

DownloadTarball 会先解析版本(若传 latest 则查询 dist-tags),再从 dist.tarball 流式写入目标文件,避免整包载入内存:

示例 1: 下载指定版本

go
package main

import (
    "context"
    "fmt"
    "log"
    "os"

    "github.com/scagogogo/npm-skills/pkg/registry"
)

func main() {
    client := registry.NewRegistry()
    ctx := context.Background()

    packageName := "axios"
    version := "1.0.0"
    destPath := "./axios-1.0.0.tgz"

    // 删除已存在的文件(如果有)
    os.Remove(destPath)

    fmt.Printf("开始下载 %s@%s...\n", packageName, version)

    err := client.DownloadTarball(ctx, packageName, version, destPath)
    if err != nil {
        log.Fatalf("下载失败: %v", err)
    }

    // 验证文件
    info, err := os.Stat(destPath)
    if err != nil {
        log.Fatalf("文件状态检查失败: %v", err)
    }

    fmt.Printf("下载成功!\n")
    fmt.Printf("文件大小: %d bytes\n", info.Size())
}

示例 2: 使用 CNPM 镜像下载(中国大陆用户推荐)

go
package main

import (
    "context"
    "fmt"
    "log"
    "os"

    "github.com/scagogogo/npm-skills/pkg/registry"
)

func main() {
    // 使用 CNPM 镜像,下载速度更快
    options := registry.NewOptions().SetRegistryURL(registry.RegistryUrlCnpm)
    client := registry.NewRegistry(options)

    ctx := context.Background()
    packageName := "react"
    version := "18.2.0"
    destDir := "/tmp/npm-tarballs"

    // 确保目标目录存在
    if err := os.MkdirAll(destDir, 0755); err != nil {
        log.Fatalf("创建目录失败: %v", err)
    }

    destPath := fmt.Sprintf("%s/%s-%s.tgz", destDir, packageName, version)
    os.Remove(destPath)

    fmt.Printf("使用 CNPM 镜像下载 %s@%s...\n", packageName, version)

    err := client.DownloadTarball(ctx, packageName, version, destPath)
    if err != nil {
        log.Fatalf("下载失败: %v", err)
    }

    info, _ := os.Stat(destPath)
    fmt.Printf("下载成功!文件大小: %d bytes\n", info.Size())
}

示例 3: 下载最新版本 (latest)

go
package main

import (
    "context"
    "fmt"
    "log"
    "os"

    "github.com/scagogogo/npm-skills/pkg/registry"
)

func main() {
    client := registry.NewRegistry()
    ctx := context.Background()

    packageName := "vue"
    version := "latest"
    destPath := "./vue-latest.tgz"

    // 获取版本信息
    versionInfo, err := client.GetPackageVersion(ctx, packageName, version)
    if err != nil {
        log.Fatalf("获取版本信息失败: %v", err)
    }

    fmt.Printf("最新版本: %s\n", versionInfo.Version)

    os.Remove(destPath)
    err = client.DownloadTarball(ctx, packageName, version, destPath)
    if err != nil {
        log.Fatalf("下载失败: %v", err)
    }

    info, _ := os.Stat(destPath)
    fmt.Printf("下载成功!文件大小: %d bytes\n", info.Size())
}

示例 4: 批量下载多个包

批量下载时,多个 goroutine 共享同一个 Registry 实例(其内部 *http.Client 与连接池并发安全),各自独立写盘、互不阻塞:

go
package main

import (
    "context"
    "fmt"
    "log"
    "os"
    "path/filepath"
    "sync"

    "github.com/scagogogo/npm-skills/pkg/registry"
)

func main() {
    client := registry.NewRegistry()
    ctx := context.Background()

    packages := []struct {
        name    string
        version string
    }{
        {"react", "18.2.0"},
        {"vue", "3.4.0"},
        {"angular", "17.3.0"},
    }

    destDir := "/tmp/npm-packages"
    os.MkdirAll(destDir, 0755)

    var wg sync.WaitGroup

    for _, pkg := range packages {
        wg.Add(1)
        go func(name, version string) {
            defer wg.Done()

            destPath := filepath.Join(destDir, fmt.Sprintf("%s-%s.tgz", name, version))
            os.Remove(destPath)

            err := client.DownloadTarball(ctx, name, version, destPath)
            if err != nil {
                log.Printf("下载 %s@%s 失败: %v\n", name, version, err)
                return
            }

            info, _ := os.Stat(destPath)
            fmt.Printf("✅ %s@%s: %d bytes\n", name, version, info.Size())
        }(pkg.name, pkg.version)
    }

    wg.Wait()
    fmt.Println("全部下载完成!")
}

运行示例

bash
go mod init tarball-example
go get github.com/scagogogo/npm-skills
go run main.go

下一步

基于 MIT 协议发布。