Skip to content

Commit 6af2971

Browse files
committed
feat: Upload large file from aria2
1 parent 5316679 commit 6af2971

File tree

4 files changed

+121
-30
lines changed

4 files changed

+121
-30
lines changed

debug

14 KB
Binary file not shown.

onedrive/client.go

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package onedrive
22

33
import (
4+
"bufio"
45
"bytes"
56
"encoding/json"
67
"fmt"
@@ -81,24 +82,42 @@ func (client *Client) CreateUploadSession(path string) (string, string) {
8182
}
8283

8384
//UploadChunk 上传文件片
84-
func (client *Client) UploadChunk(url string, from int, to int, total int, stream *os.File) (string, string) {
85+
func (client *Client) UploadChunk(url string, from int, to int, total int, stream *os.File, reader *bufio.Reader) (string, string) {
8586
headers := make(map[string]string)
8687
headers["Content-Length"] = strconv.Itoa(to - from + 1)
8788
headers["Content-Range"] = fmt.Sprintf("bytes %d-%d/%d", from, to, total)
88-
res := client.apiChunkPut(url, stream, headers)
89+
var res Response
90+
if reader == nil {
91+
res = client.apiChunkPut(url, stream, headers, nil)
92+
} else {
93+
buf := make([]byte, to-from+1)
94+
_, err := reader.Read(buf)
95+
if err != nil {
96+
return "", err.Error()
97+
}
98+
res = client.apiChunkPut(url, stream, headers, &buf)
99+
}
89100
if res.Success {
90101
return res.ResString, ""
91102
}
92103
return "", res.Error.Error.Message
93104
}
94105

95106
//apiChunkPut 发送分片PUT请求
96-
func (client *Client) apiChunkPut(url string, stream *os.File, headers map[string]string) Response {
107+
func (client *Client) apiChunkPut(url string, stream *os.File, headers map[string]string, data *[]byte) Response {
97108
if client.Tried > maxTry {
98109
return buildResponseResult("PUT failed, reached the maximum number of attempts.", 0)
99110
}
111+
var (
112+
req *http.Request
113+
err error
114+
)
115+
if data == nil {
116+
req, err = http.NewRequest("PUT", url, stream)
117+
} else {
118+
req, err = http.NewRequest("PUT", url, bytes.NewReader(*data))
119+
}
100120

101-
req, err := http.NewRequest("PUT", url, stream)
102121
if err != nil {
103122
return buildResponseResult(err.Error(), 0)
104123
}
@@ -116,7 +135,7 @@ func (client *Client) apiChunkPut(url string, stream *os.File, headers map[strin
116135
res, err := client.HTTPClient.Do(req)
117136
if err != nil {
118137
client.Tried++
119-
return client.apiChunkPut(url, stream, headers)
138+
return client.apiChunkPut(url, stream, headers, data)
120139
}
121140
defer res.Body.Close()
122141

task/TaskAdapter.go

Lines changed: 81 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package task
22

33
import (
4+
"bufio"
45
"encoding/json"
56
"fmt"
67
"log"
@@ -11,6 +12,7 @@ import (
1112
)
1213

1314
const uploadThreadNum int = 4
15+
const aria2ChunkSize int = 10 * 1024 * 1024
1416

1517
type chunkFile struct {
1618
ID int `json:"id"`
@@ -23,14 +25,15 @@ type chunkFile struct {
2325
}
2426

2527
type oneDriveUploadAttr struct {
26-
Fname string `json:"fname"`
27-
Path string `json:"path"`
28-
Objname string `json:"objname"`
29-
SavePath string `json:"savePath"`
30-
Fsize uint64 `json:"fsize"`
31-
PicInfo string `json:"picInfo"`
32-
PolicyID int `json:"policyId"`
33-
Chunks []chunkFile `json:"chunks"`
28+
Fname string `json:"fname"`
29+
Path string `json:"path"`
30+
Objname string `json:"objname"`
31+
SavePath string `json:"savePath"`
32+
Fsize uint64 `json:"fsize"`
33+
PicInfo string `json:"picInfo"`
34+
PolicyID int `json:"policyId"`
35+
Chunks []chunkFile `json:"chunks"`
36+
OriginPath string `json:"originPath"`
3437
}
3538

3639
//OneDriveUpload OneDrive上传类型Task
@@ -78,9 +81,9 @@ func (task *OneDriveUpload) Excute() {
7881
}
7982
Client.Init()
8083

81-
if task.Type == "uploadSingleToOnedrive" {
84+
if task.Type == "uploadSingleToOnedrive" || task.Type == "UploadRegularRemoteDownloadFileToOnedrive" {
8285
task.uploadRegularFile(&Client)
83-
} else if task.Type == "uploadChunksToOnedrive" {
86+
} else if task.Type == "uploadChunksToOnedrive" || task.Type == "UploadLargeRemoteDownloadFileToOnedrive" {
8487
task.uploadChunks(&Client)
8588
}
8689

@@ -124,19 +127,28 @@ func (task *OneDriveUpload) uploadSingleChunk(chunk Chunk, Client *onedrive.Clie
124127

125128
var r *os.File
126129
var err error
130+
var bfRd *bufio.Reader
127131
if chunk.Type == 0 {
128132
r, err = os.Open(chunk.ChunkPath)
133+
bfRd = nil
129134
} else {
130135
r, err = os.Open(chunk.ChunkPath)
136+
r.Seek(int64(chunk.From), 0)
137+
bfRd = bufio.NewReader(r)
131138
}
132139

133140
if err != nil {
134141
task.Log("[Error] Failed to open file," + err.Error())
135142
task.Error()
136143
return false
137144
}
145+
var uploadErr string
146+
if bfRd == nil {
147+
_, uploadErr = Client.UploadChunk(url, chunk.From, chunk.To, int(task.Attr.Fsize), r, nil)
148+
} else {
149+
_, uploadErr = Client.UploadChunk(url, chunk.From, chunk.To, int(task.Attr.Fsize), r, bfRd)
150+
}
138151

139-
_, uploadErr := Client.UploadChunk(url, chunk.From, chunk.To, int(task.Attr.Fsize), r)
140152
if uploadErr != "" {
141153
task.Log("[Error] Failed to upload chunk," + uploadErr)
142154
task.Error()
@@ -158,23 +170,62 @@ func (task *OneDriveUpload) buildChunks() ([]Chunk, string) {
158170
var chunkList []Chunk
159171
var offset int
160172

161-
for _, v := range task.Attr.Chunks {
173+
if chunkType == 0 {
174+
175+
for _, v := range task.Attr.Chunks {
176+
177+
var (
178+
chunkPath string
179+
chunkSize int
180+
)
181+
chunkPath = task.BasePath + "public/uploads/chunks/" + v.ObjName + ".chunk"
182+
183+
fileInfo, err := os.Stat(chunkPath)
184+
if os.IsNotExist(err) {
185+
return chunkList, "Chunk file " + chunkPath + " not exist"
186+
}
187+
chunkSize = int(fileInfo.Size())
162188

163-
chunkPath := task.BasePath + "public/uploads/chunks/" + v.ObjName + ".chunk"
189+
chunkList = append(chunkList, Chunk{
190+
Type: chunkType,
191+
From: offset,
192+
To: offset + chunkSize - 1,
193+
ChunkPath: chunkPath,
194+
})
195+
196+
offset += chunkSize
197+
}
198+
199+
} else {
200+
for {
201+
202+
var (
203+
chunkPath string
204+
chunkSize int
205+
)
206+
207+
chunkPath = task.Attr.OriginPath
208+
if uint64(offset+aria2ChunkSize) > task.Attr.Fsize {
209+
chunkSize = int(task.Attr.Fsize) - offset
210+
} else {
211+
chunkSize = aria2ChunkSize
212+
}
213+
214+
chunkList = append(chunkList, Chunk{
215+
Type: chunkType,
216+
From: offset,
217+
To: offset + chunkSize - 1,
218+
ChunkPath: chunkPath,
219+
})
220+
221+
offset += chunkSize
222+
223+
if offset >= int(task.Attr.Fsize) {
224+
break
225+
}
164226

165-
fileInfo, err := os.Stat(chunkPath)
166-
if os.IsNotExist(err) {
167-
return chunkList, "Chunk file " + chunkPath + " not exist"
168227
}
169-
chunkSize := int(fileInfo.Size())
170228

171-
chunkList = append(chunkList, Chunk{
172-
Type: chunkType,
173-
From: offset,
174-
To: offset + chunkSize - 1,
175-
ChunkPath: chunkPath,
176-
})
177-
offset += chunkSize
178229
}
179230

180231
return chunkList, ""
@@ -183,7 +234,12 @@ func (task *OneDriveUpload) buildChunks() ([]Chunk, string) {
183234

184235
func (task *OneDriveUpload) uploadRegularFile(Client *onedrive.Client) {
185236
var filePath string
186-
filePath = task.BasePath + "public/uploads/" + task.Attr.SavePath + "/" + task.Attr.Objname
237+
if task.Type == "UploadRegularRemoteDownloadFileToOnedrive" {
238+
filePath = task.Attr.OriginPath
239+
} else {
240+
filePath = task.BasePath + "public/uploads/" + task.Attr.SavePath + "/" + task.Attr.Objname
241+
}
242+
187243
r, err := os.Open(filePath)
188244
defer r.Close()
189245
if err != nil {

task/task.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,22 @@ func (task *taskInfo) Run() {
5858
BasePath: task.siteInfo["basePath"],
5959
}
6060
newTask.Init()
61+
case task.sqlInfo.TaskType == "UploadRegularRemoteDownloadFileToOnedrive":
62+
newTask = &OneDriveUpload{
63+
Info: task,
64+
Tried: 0,
65+
Type: task.sqlInfo.TaskType,
66+
BasePath: task.siteInfo["basePath"],
67+
}
68+
newTask.Init()
69+
case task.sqlInfo.TaskType == "UploadLargeRemoteDownloadFileToOnedrive":
70+
newTask = &OneDriveUpload{
71+
Info: task,
72+
Tried: 0,
73+
Type: task.sqlInfo.TaskType,
74+
BasePath: task.siteInfo["basePath"],
75+
}
76+
newTask.Init()
6177
}
6278
newTask.Excute()
6379
}

0 commit comments

Comments
 (0)