在本教程中,我们将构建一个功能强大的下载器,允许从Google Drive和其他云提供商下载文件。借助 Golang 高效的并发模式,您将能够同时管理多个下载、流式传输大文件并实时跟踪进度。无论您是下载一些小文件还是处理大型数据集,该项目都将展示如何构建可扩展且强大的下载器,该下载器可以轻松扩展以支持多个云平台。
如果您正在寻找一种简化和自动下载大文件的方法,本教程非常适合您。最后,您将拥有一个灵活且可定制的基于 Go 的下载器来满足您的需求。
如果您只是想在 UI 中使用此下载器,请访问 evolvasdev.com 阅读完整文章和 Go Downloader 的 Github。您将找到使其快速运行的文档。
Go 并发模式:
了解如何使用 Goroutines、通道和互斥体有效地处理多个并发文件下载。
流式传输大量下载:
探索如何在有效管理内存和系统资源的同时传输大文件。
并发文件下载:
了解如何同时下载文件,加快进程并提高性能。
实时进度更新:
实施进度跟踪以提供下载状态的实时反馈。
处理中断和取消:
了解如何优雅地取消一项或所有正在进行的下载。
注:本教程仅关注核心下载逻辑。
在做任何事情之前,请首先确保正确设置您的环境,以避免将来出现潜在的错误。
使用以下内容在项目的根目录创建一个 makefile。
# Load environment variables from .env file include ./.env # To run the application run: build @./bin/go-downloader # Build the application build: @go build -tags '!dev' -o bin/go-downloader # Database migration status db-status: @GOOSE_DRIVER=postgres GOOSE_DBSTRING=$(DB_URL) goose -dir=$(migrationPath) status # Run database migrations up: @GOOSE_DRIVER=postgres GOOSE_DBSTRING=$(DB_URL) goose -dir=$(migrationPath) up # Roll back the last database migration down: @GOOSE_DRIVER=postgres GOOSE_DBSTRING=$(DB_URL) goose -dir=$(migrationPath) down # Reset database migrations reset: @GOOSE_DRIVER=postgres GOOSE_DBSTRING=$(DB_URL) goose -dir=$(migrationPath) reset
go-downloader/ ├── api ├── config ├── migrations ├── service ├── setting ├── store ├── types ├── util ├── .env ├── .air.toml ├── Makefile ├── go.mod ├── go.sum └── main.go
根据需要在根目录中创建 .env 文件或处理环境变量,我们将使用 joho/godotenv 包。
GOOGLE_CLIENT_ID GOOGLE_CLIENT_SECRET SESSION_SECRET=something-super-secret APP_URL=http://localhost:3000 POSTGRES_USER POSTGRES_PASSWORD POSTGRES_DB
我们现在将开始创建处理所有传入请求的 Web 服务器。
注意! 本指南的主要部分从这里开始。准备好潜入吧!
首先,在 api 文件夹 api.go 和 Route.go 中创建以下文件
所有API路由都将在这里定义。我们创建一个采用 env 配置的 NewRouter 结构,允许所有路由和处理程序访问环境变量。
package api import ( "github.com/gofiber/fiber/v2" "github.com/nilotpaul/go-downloader/config" ) type Router struct { env config.EnvConfig } func NewRouter(env config.EnvConfig) *Router { return &Router{ env: env, } } func (h *Router) RegisterRoutes(r fiber.Router) { r.Get("/healthcheck", func(c *fiber.Ctx) error { return c.JSON("OK") }) }
在这里,我们将在启动服务器之前添加所有必要的中间件,例如 CORS 和日志记录。
type APIServer struct { listenAddr string env config.EnvConfig } func NewAPIServer(listenAddr string, env config.EnvConfig) *APIServer { return &APIServer{ listenAddr: listenAddr, env: env, } } func (s *APIServer) Start() error { app := fiber.New(fiber.Config{ AppName: "Go Downloader", }) handler := NewRouter() handler.RegisterRoutes(app) log.Printf("Server started on http://localhost:%s", s.listenAddr) return app.Listen(":" s.listenAddr) }
这是 main.go 文件中的主包,它将作为整体的入口点。
func main() { // Loads all Env vars from .env file. env := config.MustLoadEnv() log.Fatal(s.Start()) }
这足以启动服务器并测试它。
air
就是这样。?
curl http://localhost:3000/healthcheck
响应应该正常,状态为 200
我们需要实施一个可扩展的解决方案,以便在必要时添加对多个云提供商的支持。
// Better to keep it in a seperate folder. // Specific only to OAuth Providers. type OAuthProvider interface { Authenticate(string) error GetAccessToken() string GetRefreshToken() string RefreshToken(*fiber.Ctx, string, bool) (*oauth2.Token, error) IsTokenValid() bool GetAuthURL(state string) string CreateOrUpdateAccount() (string, error) CreateSession(c *fiber.Ctx, userID string) error UpdateTokens(*GoogleAccount) error } type ProviderRegistry struct { Providers map[string]OAuthProvider } func NewProviderRegistry() *ProviderRegistry { return &ProviderRegistry{ Providers: make(map[string]OAuthProvider), } } func (r *ProviderRegistry) Register(providerName string, p OAuthProvider) { r.Providers[providerName] = p } func (r *ProviderRegistry) GetProvider(providerName string) (OAuthProvider, error) { p, exists := r.Providers[providerName] if !exists { return nil, fmt.Errorf("Provider not found") } return p, nil }
ProviderRegistry 作为一个中央地图来保存我们所有的 OAuth 提供者。当我们初始化我们的提供者时,我们将在这个映射中注册它们。这使我们能够在整个服务过程中轻松访问任何注册提供商的功能。
您稍后会看到此操作。
我们将根据提供的环境变量注册我们的提供程序。
func InitStore(env config.EnvConfig) *ProviderRegistry { r := NewProviderRegistry() if len(env.GoogleClientSecret) != 0 || len(env.GoogleClientID) != 0 { googleProvider := NewGoogleProvider(googleProviderConfig{ googleClientID: env.GoogleClientID, googleClientSecret: env.GoogleClientSecret, googleRedirectURL: env.AppURL "/callback/google", }, env) r.Register("google", googleProvider) } return r }
在此处阅读全文。
我们已经为 Go 中的 Google Drive Downloader 奠定了基础,涵盖了设置项目结构、处理 Google OAuth 等关键组件,并为未来的扩展奠定了基础。一路上,我们触及了一些重要的话题:
这对于一篇文章来说已经足够了,因为事情变得相当长了!我们将在第 2 部分中回来完成我们的工作,我们将在其中处理主要的下载功能。
在那之前,请随意探索我的 GitHub 中的当前实现,并继续关注后续步骤。祝您下载愉快!
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3