Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions fs/graph/drive_item.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,24 @@ func GetItemContent(id string, auth *Auth) ([]byte, uint64, error) {
return buf.Bytes(), uint64(n), err
}

// size of the individual requests used for downloading large files
const downloadChunkSize = 10 * 1024 * 1024

// chunkRanges splits a file of the given size into inclusive byte ranges of at
// most downloadChunkSize bytes. There is no empty trailing range when the size
// is an exact multiple of the chunk size (the server answers those with a 416).
func chunkRanges(size uint64) [][2]uint64 {
var ranges [][2]uint64
for start := uint64(0); start < size; start += downloadChunkSize {
end := start + downloadChunkSize - 1
if end >= size {
end = size - 1
}
ranges = append(ranges, [2]uint64{start, end})
}
return ranges
}

// GetItemContentStream is the same as GetItemContent, but writes data to an
// output reader. This function assumes a brand-new io.Writer is used, so
// "output" must be truncated if there is content already in the io.Writer
Expand All @@ -133,7 +151,6 @@ func GetItemContentStream(id string, auth *Auth, output io.Writer) (uint64, erro
return 0, err
}

const downloadChunkSize = 10 * 1024 * 1024
downloadURL := fmt.Sprintf("/me/drive/items/%s/content", id)
if item.Size <= downloadChunkSize {
// simple one-shot download
Expand All @@ -147,9 +164,8 @@ func GetItemContentStream(id string, auth *Auth, output io.Writer) (uint64, erro

// multipart download
var n uint64
for i := 0; i < int(item.Size/downloadChunkSize)+1; i++ {
start := i * downloadChunkSize
end := start + downloadChunkSize - 1
for _, r := range chunkRanges(item.Size) {
start, end := r[0], r[1]
log.Info().
Str("id", item.ID).
Str("name", item.Name).
Expand Down
11 changes: 11 additions & 0 deletions fs/graph/drive_item_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,14 @@ func TestGetItem(t *testing.T) {
_, err = GetItemPath("/lkjfsdlfjdwjkfl", &auth)
assert.Error(t, err, "We didn't return an error for a non-existent item!")
}

func TestChunkRanges(t *testing.T) {
t.Parallel()
const c = downloadChunkSize
assert.Empty(t, chunkRanges(0))
assert.Equal(t, [][2]uint64{{0, c - 1}}, chunkRanges(c))
assert.Equal(t, [][2]uint64{{0, c - 1}, {c, c}}, chunkRanges(c+1))
// exact multiples must not request a range past the end of the file
assert.Equal(t, [][2]uint64{{0, c - 1}, {c, 2*c - 1}}, chunkRanges(2*c))
assert.Equal(t, [][2]uint64{{0, c - 1}, {c, 2*c - 1}, {2 * c, 3*c - 1}}, chunkRanges(3*c))
}