SDK 提供了分片上传(Multipart Upload)功能,可以将要上传的文件分成多个数据块(US3 里又称之为 Part)来分别上传。完整代码详见 Github。
分片上传方式
SDK 目前提供了如下几种分片上传方式:
参数名 | 说明 |
---|---|
MPut | 同步分片上传,非并发 |
AsyncMPut | 异步分片并发上传,并发数10 |
AsyncUpload | 异步分片并发上传,并发数可调 |
IOMutipartAsyncUpload | 流式并发分片上传 |
同步分片上传
MPut
实现同步分片上传,示例如下,完整代码详见 Github。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main
import (
ufsdk "github.com/ufilesdk-dev/ufile-gosdk"
"log"
)
const (
ConfigFile = "config.json"
FilePath = "FakeBigFile.txt"
KeyName = "FakeBigFile.txt"
MimeType = ""
)
func main() {
// 加载配置,创建请求
config, err := ufsdk.LoadConfig(ConfigFile)
if err != nil {
panic(err.Error())
}
req, err := ufsdk.NewFileRequest(config, nil)
if err != nil {
panic(err.Error())
}
// 同步分片上传本地文件
err = req.MPut(FilePath, KeyName, MimeType)
if err != nil {
log.Fatalf("%s\n", err.Error())
}
log.Println("文件上传成功!!")
}
异步分片上传
AsycMPut
实现异步分片上传,固定10个分片并发上传,示例如下,完整代码详见 Github。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package main
import (
ufsdk "github.com/ufilesdk-dev/ufile-gosdk"
"log"
)
const (
ConfigFile = "config.json"
FilePath = "FakeBigFile.txt"
KeyName = "FakeBigFile.txt"
MimeType = ""
)
func main() {
// 加载配置,创建请求
config, err := ufsdk.LoadConfig(ConfigFile)
if err != nil {
panic(err.Error())
}
req, err := ufsdk.NewFileRequest(config, nil)
if err != nil {
panic(err.Error())
}
// 异步分片上传本地文件
err = req.AsyncMPut(FilePath, KeyName, MimeType)
if err != nil {
log.Fatalf("%s\n", err.Error())
}
log.Println("文件上传成功!!")
}
异步并发分片上传
AsyncUpload
实现了异步并发分片上传,可自定义并发上传数量,目前允许并发数需小于30,适用于大文件加速上传。示例如下,完整代码详见 Github。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package main
import (
ufsdk "github.com/ufilesdk-dev/ufile-gosdk"
"log"
)
const (
ConfigFile = "config.json"
FilePath = "FakeBigFile.txt"
KeyName = "FakeBigFile.txt"
MimeType = ""
Jobs = 29
)
func main() {
// 加载配置,创建请求
config, err := ufsdk.LoadConfig(ConfigFile)
if err != nil {
panic(err.Error())
}
req, err := ufsdk.NewFileRequest(config, nil)
if err != nil {
panic(err.Error())
}
// 异步分片上传本地文件
err = req.AsyncUpload(FilePath, KeyName, MimeType, Jobs)
if err != nil {
log.Fatalf("%s\n", err.Error())
}
log.Println("文件上传成功!!")
}
流式并发分片上传
IOMultipartAsyncUpload
通过传入io.Reader 实现流式并发分片上传,使用于文件大小还不确定的情况下开始上传。示例如下,完整代码详见 Github。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package main
import (
ufsdk "github.com/ufilesdk-dev/ufile-gosdk"
"log"
"os"
)
const (
ConfigFile = "config.json"
FilePath = "FakeBigFile.txt"
KeyName = "FakeBigFile.txt"
MimeType = ""
)
func main() {
// 加载配置,创建请求
config, err := ufsdk.LoadConfig(ConfigFile)
if err != nil {
panic(err.Error())
}
req, err := ufsdk.NewFileRequest(config, nil)
if err != nil {
panic(err.Error())
}
// 流式分片上传本地文件
f, err := os.Open(FilePath)
if err != nil {
panic(err.Error())
}
err = req.IOMutipartAsyncUpload(f, KeyName, MimeType)
if err != nil {
log.Fatalf("%s\n", err.Error())
}
log.Println("文件上传成功!!")
}
实际上,一个完整的分片上传分为初始化分片 -> 上传分片 -> 完成分片三个阶段,具体见分片上传流程
分片上传流程
SDK 提供以下方法完成分片上传,接口说明如下
接口名 | 说明 |
---|---|
InitiateMultipartUpload | 初始化分片上传,US3 API 文档详见 InitiateMultipartUpload |
UploadPart | 上传一个分片,US3 API 文档详见 UploadPart |
AbortMultipartUpload | 终止分片上传,US3 API 文档详见 AbortMultipartUpload |
FinishMultipartUpload | 完成分片上传,US3 API 文档详见 FinishMultipartUpload |
分片上传流程示例
一个完整的本地文件分片上传流程示例如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package main
import (
"bytes"
ufsdk "github.com/ufilesdk-dev/ufile-gosdk"
"io"
"os"
)
const (
ConfigFile = "config.json"
FilePath = "FakeBigFile.txt"
KeyName = "FakeBigFile.txt"
MimeType = ""
)
func checkErr (err error) {
if err != nil {
panic(err)
}
}
func main() {
// 加载配置,创建请求
config, err := ufsdk.LoadConfig(ConfigFile)
if err != nil {
panic(err.Error())
}
req, err := ufsdk.NewFileRequest(config, nil)
if err != nil {
panic(err.Error())
}
file, err := os.Open(FilePath)
checkErr(err)
defer file.Close()
// 初始化分片
state, err := req.InitiateMultipartUpload(KeyName, MimeType)
checkErr(err)
// 逐个上传分片, 若出错则终止上传
chunk := make([]byte, state.BlkSize)
var pos int
for {
bytesRead, fileErr := file.Read(chunk)
if fileErr == io.EOF || bytesRead == 0 { //后面直接读到了结尾
break
}
buf := bytes.NewBuffer(chunk[:bytesRead])
err := req.UploadPart(buf, state, pos)
if err != nil {
req.AbortMultipartUpload(state)
checkErr(err)
}
pos++
}
// 完成分片
err = req.FinishMultipartUpload(state)
checkErr(err)
}
错误码
HTTP 状态码 | RetCode | ErrMsg | 描述 |
---|---|---|---|
400 | -148653 | bucket not exists | 存储空间不存在 |
400 | -15036 | check md5 failed | MD5校验失败 |
401 | -148643 | no authorization found | 上传凭证错误 |
403 | -148643 | invalid signature | API公私钥错误KeyName包含%、#、? |