From 694cdfdd48ee10ed09cae8caad75f273ef623ebb Mon Sep 17 00:00:00 2001 From: TaoZeyu Date: Thu, 8 Aug 2024 13:49:39 +0800 Subject: [PATCH 1/2] feat(project): add simple function --- README.md | 4 +++ get.go | 66 ++++++++++++++++++++++++++++++++++++++++++++++ oget.go => task.go | 0 3 files changed, 70 insertions(+) create mode 100644 get.go rename oget.go => task.go (100%) diff --git a/README.md b/README.md index 547b751..f8e4f20 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,10 @@ $ go install github.com/oomol-lab/oget ```go import "github.com/oomol-lab/oget" +oget.OGet { + FilePath: "/path/to/save/file.bin" +} + task, err := oget.CreateGettingTask(&oget.RemoteFile{ URL: "https://github.com/oomol-lab/oget/raw/main/tests/target.bin", }) diff --git a/get.go b/get.go new file mode 100644 index 0000000..2c3c154 --- /dev/null +++ b/get.go @@ -0,0 +1,66 @@ +package oget + +import ( + "context" + "time" +) + +type OGet struct { + // the URL of the file to download. + URL string + // the path to save the downloaded file. + FilePath string + // the context for the http request. + // if the value is nil, the context will be context.Background(). + Context context.Context + // the maximum amount of time a dial will wait for a connect or copy to complete. + // the default is 10 seconds. + Timeout time.Duration + // the User-Agent header field value. + // if the value is empty, the User-Agent header will not be set. + Useragent string + // the Referer header field value. + // if the value is empty, the Referer header will not be set. + Referer string + // the maximum number of idle (keep-alive) connections to keep per-host. + // the default is 16. + MaxIdleConnsPerHost int + // the SHA512 code of the file. + // if the code is empty, the file will not be checked. + SHA512 string + // PartsPath is the path to save the temp files of downloaded parts. + // if the value is empty, the temp files will be saved in the same directory as the FilePath. + PartsPath string + // the name of the part file. + // if the value is empty, the name will be the same as the file name. + PartName string + // the number of parts to download the file. + // if the value is less than or equal to 0, the file will be downloaded in one part. + Parts int + // the progress listener. + // if the value is nil, the progress will not be listened. + ListenProgress ProgressListener +} + +func (o OGet) Get() (func() error, error) { + clean := func() error { return nil } + task, err := CreateGettingTask(&RemoteFile{ + Context: o.Context, + Timeout: o.Timeout, + URL: o.URL, + Useragent: o.Useragent, + Referer: o.Referer, + MaxIdleConnsPerHost: o.MaxIdleConnsPerHost, + }) + if err != nil { + return clean, err + } + return task.Get(&GettingConfig{ + FilePath: o.FilePath, + SHA512: o.SHA512, + PartsPath: o.PartsPath, + PartName: o.PartName, + Parts: o.Parts, + ListenProgress: o.ListenProgress, + }) +} diff --git a/oget.go b/task.go similarity index 100% rename from oget.go rename to task.go From af6cae5adf5e9453e04d8c3818bb2bcd98c30115 Mon Sep 17 00:00:00 2001 From: TaoZeyu Date: Thu, 8 Aug 2024 14:04:04 +0800 Subject: [PATCH 2/2] docs(README): support new API --- README.md | 82 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index f8e4f20..44c4308 100644 --- a/README.md +++ b/README.md @@ -13,19 +13,11 @@ $ go install github.com/oomol-lab/oget ```go import "github.com/oomol-lab/oget" -oget.OGet { - FilePath: "/path/to/save/file.bin" -} - -task, err := oget.CreateGettingTask(&oget.RemoteFile{ - URL: "https://github.com/oomol-lab/oget/raw/main/tests/target.bin", -}) -if err != nil { - panic(err) -} -_, err = task.Get(&oget.GettingConfig{ +_, err := OGet{ + URL: "https://github.com/oomol-lab/oget/raw/main/tests/target.bin", FilePath: "/path/to/save/file.bin", -}) +}.Get() + if err != nil { panic(err) } @@ -40,20 +32,16 @@ It splits large files into multiple smaller parts for parallel downloading, then ```go import "github.com/oomol-lab/oget" -task, err := oget.CreateGettingTask(&oget.RemoteFile{ - URL: "https://github.com/oomol-lab/oget/raw/main/tests/target.bin", -}) -if err != nil { - panic(err) -} -_, err = task.Get(&oget.GettingConfig{ +_, err := OGet{ + URL: "https://github.com/oomol-lab/oget/raw/main/tests/target.bin", // Path to store the final file - FilePath: "/path/to/save/file.bin", + FilePath: "/path/to/save/file.bin", // Number of file parts for splitting and parallel downloading Parts: 4, // If not specified, defaults to the same directory as `FilePath` PartsPath: "/path/to/save/temp/files", -}) +}.Get() + if err != nil { panic(err) } @@ -66,15 +54,10 @@ if err != nil { ```go import "github.com/oomol-lab/oget" -task, err := oget.CreateGettingTask(&oget.RemoteFile{ - URL: "https://github.com/oomol-lab/oget/raw/main/tests/target.bin", -}) -if err != nil { - panic(err) -} var mux sync.Mutex -_, err = task.Get(&oget.GettingConfig{ - FilePath: "/path/to/save/file.bin", +_, err := OGet{ + URL: "https://github.com/oomol-lab/oget/raw/main/tests/target.bin", + FilePath: "/path/to/save/file.bin", ListenProgress: func(event oget.ProgressEvent) { // Callback may be invoked in multiple threads // Use a lock to ensure thread safety @@ -93,7 +76,8 @@ _, err = task.Get(&oget.GettingConfig{ // Total number of bytes in this step total := event.Total }, -}) +}.Get() + if err != nil { panic(err) } @@ -106,16 +90,12 @@ After downloading, the library performs a SHA512 checksum on the entire file. If ```go import "github.com/oomol-lab/oget" -task, err := oget.CreateGettingTask(&oget.RemoteFile{ - URL: "https://github.com/oomol-lab/oget/raw/main/tests/target.bin", -}) -if err != nil { - panic(err) -} -_, err = task.Get(&oget.GettingConfig{ +_, err := OGet{ + URL: "https://github.com/oomol-lab/oget/raw/main/tests/target.bin", FilePath: "/path/to/save/file.bin", SHA512: "d286fbb1fab9014fdbc543d09f54cb93da6e0f2c809e62ee0c81d69e4bf58eec44571fae192a8da9bc772ce1340a0d51ad638cdba6118909b555a12b005f2930", -}) +}.Get() + if err != nil { if sha512Error, ok := err.(oget.SHA512Error); ok { // Failed due to SHA512 verification failure @@ -128,6 +108,32 @@ if err != nil { During a download, oget creates a temporary file with the extension `*.downloading` (regardless of whether it's split into parts). If a download fails due to network issues and the temporary file is not deleted, resuming the download will retain the progress from the previous attempt. To implement resuming downloads, ignore download failures caused by network issues and retry the download. +```go +import "github.com/oomol-lab/oget" +success := false + +for i := 0; i < 10; i++ { + clean, err := OGet{ + URL: "https://github.com/oomol-lab/oget/raw/main/tests/target.bin", + FilePath: "/path/to/save/file.bin", + Parts: 4, + }.Get() + if err != nil { + if sha512Error, ok := err.(oget.SHA512Error); ok { + clean() + panic(sha512Error) + } + fmt.Printf("download failed with error and retry %s", err) + } else { + success = true + } +} +if !success { + panic("download fail") +} +``` +The above method will send a request to the server for the file meta each time you retry. If you don't want this meaningless request, you can use the following method. + First, create a `task` object using `oget.CreateGettingTask`. This step only fetches file metadata from the server without starting the download. If this step fails, it should be considered a complete failure of the download task. ```go