https://github.com/tus/tus-go-client
Full-featured Go client for TUS resumable upload protocol
https://github.com/tus/tus-go-client
golang tus tus-protocol
Last synced: 6 months ago
JSON representation
Full-featured Go client for TUS resumable upload protocol
- Host: GitHub
- URL: https://github.com/tus/tus-go-client
- Owner: tus
- License: apache-2.0
- Created: 2023-01-11T19:46:20.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2024-11-10T08:57:29.000Z (11 months ago)
- Last Synced: 2025-03-17T20:21:20.786Z (7 months ago)
- Topics: golang, tus, tus-protocol
- Language: Go
- Homepage:
- Size: 174 KB
- Stars: 12
- Watchers: 4
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# tusgo
[](https://codecov.io/gh/bdragon300/tusgo)
[](https://goreportcard.com/report/github.com/bdragon300/tusgo)

[](https://pkg.go.dev/github.com/bdragon300/tusgo)
Full-featured Go client for [TUS](https://tus.io), a protocol for resumable uploads built on HTTP.
Documentation is available at [pkg.go.dev](https://pkg.go.dev/github.com/bdragon300/tusgo)
## Features
* Resumable Upload writer with chunked and streamed mode support. Conforms the `io.Writer`/`io.ReaderFrom`, which allows
to use the standard utils such as `io.Copy`
* Client for Upload manipulation such as creation, deletion, concatenation, etc.
* Intermediate data store (for chunked Uploads) now is only in-memory
* Server extensions are supported:
* `creation` extension -- upload creation
* `creation-defer-length` -- upload creation without size. Its size is set on the first data transfer
* `creation-with-upload` -- upload creation and data transferring in one HTTP request
* `expiration` -- parsing the upload expiration info
* `checksum` -- data integrity verification for chunked uploads. Many checksum algorithms from Go stdlib are
supported
* `checksum-trailer` -- data integrity verification for streamed uploads. Checksum hash is calculated for all data
in stream and is put to HTTP trailer
* `termination` -- deleting uploads from server
* `concatenation` -- merge finished uploads into one
* `concatenation-unfinished` -- merge unfinished uploads (data streams) into one upload## Installation
```shell
go get github.com/bdragon300/tusgo
```Go v1.18 or newer is required
## Examples
### Minimal file transfer example
```go
package mainimport (
"fmt"
"io"
"net/http"
"net/url"
"os"
)
import "github.com/bdragon300/tusgo"func main() {
baseURL, _ := url.Parse("http://example.com/files")
cl := tusgo.NewClient(http.DefaultClient, baseURL)// Assume that the Upload has been created on server earlier with size 1KiB
u := tusgo.Upload{Location: "http://example.com/files/foo/bar", RemoteSize: 1024 * 1024}
// Open a file we want to upload
f, err := os.Open("/tmp/file.txt")
if err != nil {
panic(err)
}
defer f.Close()s := tusgo.NewUploadStream(cl, &u)
// Set stream and file pointers to be equal to the remote pointer
if _, err = s.Sync(); err != nil {
panic(err)
}
if _, err = f.Seek(s.Tell(), io.SeekStart); err != nil {
panic(err)
}
written, err := io.Copy(s, f)
if err != nil {
panic(fmt.Sprintf("Written %d bytes, error: %s, last response: %v", written, err, s.LastResponse))
}
fmt.Printf("Written %d bytes\n", written)
}
```### Create an Upload and transfer the file with retrying on error
```go
package mainimport (
"errors"
"io"
"net"
"net/http"
"net/url"
"os"
"time"
)
import "github.com/bdragon300/tusgo"func UploadWithRetry(dst *tusgo.UploadStream, src *os.File) error {
// Set stream and file pointer to be equal to the remote pointer
// (if we resume the upload that was interrupted earlier)
if _, err := dst.Sync(); err != nil {
return err
}
if _, err := src.Seek(dst.Tell(), io.SeekStart); err != nil {
return err
}_, err := io.Copy(dst, src)
attempts := 10
for err != nil && attempts > 0 {
if _, ok := err.(net.Error); !ok && !errors.Is(err, tusgo.ErrChecksumMismatch) {
return err // Permanent error, no luck
}
time.Sleep(5 * time.Second)
attempts--
_, err = io.Copy(dst, src) // Try to resume the transfer again
}
if attempts == 0 {
return errors.New("too many attempts to upload the data")
}
return nil
}func CreateUploadFromFile(f *os.File, cl *tusgo.Client) *tusgo.Upload {
finfo, err := f.Stat()
if err != nil {
panic(err)
}u := tusgo.Upload{}
if _, err = cl.CreateUpload(&u, finfo.Size(), false, nil); err != nil {
panic(err)
}
return &u
}func main() {
baseURL, _ := url.Parse("http://example.com/files")
cl := tusgo.NewClient(http.DefaultClient, baseURL)f, err := os.Open("/tmp/file.txt")
if err != nil {
panic(err)
}
defer f.Close()
u := CreateUploadFromFile(f, cl)stream := tusgo.NewUploadStream(cl, u)
if err = UploadWithRetry(stream, f); err != nil {
panic(err)
}
}
```