|
@@ -162,39 +162,48 @@ class MultipartUploader {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- // For a 100MB file, with the default min chunk size of 5MB and a limit of 10:
|
|
|
- //
|
|
|
- // Total 20 parts
|
|
|
- // ---------
|
|
|
- // Need 1 is 10
|
|
|
- // Need 2 is 5
|
|
|
- // Need 3 is 5
|
|
|
- const need = this.options.limit - this.partsInProgress
|
|
|
- const completeChunks = this.chunkState.filter((state) => state.done).length
|
|
|
- const remainingChunks = this.chunks.length - completeChunks
|
|
|
- let minNeeded = Math.ceil(this.options.limit / 2)
|
|
|
- if (minNeeded > remainingChunks) {
|
|
|
- minNeeded = remainingChunks
|
|
|
- }
|
|
|
- if (need < minNeeded) return
|
|
|
+ const getChunkIndexes = () => {
|
|
|
+ // For a 100MB file, with the default min chunk size of 5MB and a limit of 10:
|
|
|
+ //
|
|
|
+ // Total 20 parts
|
|
|
+ // ---------
|
|
|
+ // Need 1 is 10
|
|
|
+ // Need 2 is 5
|
|
|
+ // Need 3 is 5
|
|
|
+ const need = this.options.limit - this.partsInProgress
|
|
|
+ const completeChunks = this.chunkState.filter((state) => state.done).length
|
|
|
+ const remainingChunks = this.chunks.length - completeChunks
|
|
|
+ let minNeeded = Math.ceil(this.options.limit / 2)
|
|
|
+ if (minNeeded > remainingChunks) {
|
|
|
+ minNeeded = remainingChunks
|
|
|
+ }
|
|
|
+ if (need < minNeeded) return []
|
|
|
|
|
|
- const candidates = []
|
|
|
- for (let i = 0; i < this.chunkState.length; i++) {
|
|
|
- const state = this.chunkState[i]
|
|
|
- // eslint-disable-next-line no-continue
|
|
|
- if (state.done || state.busy) continue
|
|
|
+ const chunkIndexes = []
|
|
|
+ for (let i = 0; i < this.chunkState.length; i++) {
|
|
|
+ const state = this.chunkState[i]
|
|
|
+ // eslint-disable-next-line no-continue
|
|
|
+ if (state.done || state.busy) continue
|
|
|
|
|
|
- candidates.push(i)
|
|
|
- if (candidates.length >= need) {
|
|
|
- break
|
|
|
+ chunkIndexes.push(i)
|
|
|
+ if (chunkIndexes.length >= need) {
|
|
|
+ break
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ return chunkIndexes
|
|
|
}
|
|
|
- if (candidates.length === 0) return
|
|
|
|
|
|
- this.#prepareUploadParts(candidates).then((result) => {
|
|
|
- candidates.forEach((index) => {
|
|
|
+ const chunkIndexes = getChunkIndexes()
|
|
|
+
|
|
|
+ if (chunkIndexes.length === 0) return
|
|
|
+
|
|
|
+ return this.#prepareUploadParts(chunkIndexes).then((result) => {
|
|
|
+ const { presignedUrls, headers } = result
|
|
|
+
|
|
|
+ chunkIndexes.forEach((index) => {
|
|
|
const partNumber = index + 1
|
|
|
- const prePreparedPart = { url: result.presignedUrls[partNumber], headers: result.headers }
|
|
|
+ const prePreparedPart = { url: presignedUrls[partNumber], headers: headers?.[partNumber] }
|
|
|
this.#uploadPartRetryable(index, prePreparedPart).then(() => {
|
|
|
this.#uploadParts()
|
|
|
}, (err) => {
|
|
@@ -238,8 +247,8 @@ class MultipartUploader {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
- async #prepareUploadParts (candidates) {
|
|
|
- candidates.forEach((i) => {
|
|
|
+ async #prepareUploadParts (chunkIndexes) {
|
|
|
+ chunkIndexes.forEach((i) => {
|
|
|
this.chunkState[i].busy = true
|
|
|
})
|
|
|
|
|
@@ -247,12 +256,10 @@ class MultipartUploader {
|
|
|
attempt: () => this.options.prepareUploadParts({
|
|
|
key: this.key,
|
|
|
uploadId: this.uploadId,
|
|
|
- partNumbers: candidates.map((index) => index + 1),
|
|
|
- chunks: candidates.reduce((chunks, candidate) => ({
|
|
|
- ...chunks,
|
|
|
- // Use the part number as the index
|
|
|
- [candidate + 1]: this.chunks[candidate],
|
|
|
- }), {}),
|
|
|
+ parts: chunkIndexes.map((index) => ({
|
|
|
+ number: index + 1, // Use the part number as the index
|
|
|
+ chunk: this.chunks[index],
|
|
|
+ })),
|
|
|
}),
|
|
|
})
|
|
|
|