Conversation
Add opt-in chunked uploads to FileUploader. Setting `chunkSize` sends each file as a sequence of requests, one per chunk: - multipart mode sends the chunk as the file field plus `chunkIndex` and `totalChunks` fields (names configurable via `chunkIndexParam` / `totalChunksParam`) - with `disableMultipart` the raw chunk is sent with a `Content-Range` header - `chunkRetries` retries a failed chunk before the item fails - new `onBeforeUploadChunk` / `onCompleteChunk` hooks; changing `item.url`, `item.method` or `item.headers` there targets the next chunk request - `item.cancel()` stops the remaining chunks, also when called between chunks - progress is reported across the whole file Without `chunkSize` uploads behave exactly as before. Thanks to @PauloPeres for the original implementation and API idea in #977. Closes #880 Closes #435 Co-authored-by: Paulo <p.peresjr@gmail.com>
|
Visit the preview URL for this PR (updated for commit ea46813): https://ngx-file-upload--pr1303-feat-chunked-upload-vqu3xksn.web.app (expires Thu, 08 Oct 2026 16:02:28 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: f15ad3fba241d6d58091ac579c27208d04d4562f |
added 8 commits
October 1, 2026 17:22
…nt failures - errors thrown while sending a later chunk or retry (e.g. from onBeforeUploadChunk / onCompleteChunk) ran outside FileItem.upload()'s try/catch and left the item and uploader stuck in isUploading; they now fail the item - chunkRetries now only retries network errors, 408, 429 and 5xx; other 4xx responses fail immediately instead of repeating requests that can't succeed
- cancel from onBeforeUploadChunk now stops before the chunk is sent; cancelItem no longer throws when no request exists yet - cancel from onCompleteChunk on the last chunk reports cancel - chunks keep the file's MIME type - retries wait chunkRetryDelay (default 1000ms, doubled per retry) or the server's Retry-After, and can be cancelled while waiting - retries go through onBeforeUploadChunk with chunk.retry increased - 501 and 505 are not retried - fractional chunkSize is floored so slices and Content-Range stay valid - empty files in raw mode send Content-Range: bytes */0 - a throwing hook on the first chunk reports error before complete, and an error after a chunk was sent detaches that request so the item is reported once - document per-chunk onBuildItemForm/response, item.chunk and retry delay
- restore the original order for non-chunked uploads: the request is created before onBeforeUploadItem again; chunk requests are created before onBeforeUploadChunk - cancel from any hook, including onBuildItemForm, stops before the chunk is sent; a failure after cancel is reported as cancel - rename onCompleteChunk to onSuccessChunk, it only runs for successful chunks - re-uploading an item starts from the url/method/headers it had before hooks changed them, unless the app changed them in between - a throwing app hook while the item is already reported is rethrown instead of reporting the item twice - keep a Content-Range header set by the app - cap retry delays at 30 seconds - remove excessive comments, update docs
- keep the original progress rounding for non-chunked uploads - errors thrown by chunk callbacks fail the item with status 0 and are rethrown asynchronously so the app's error handler sees them; an error thrown while reporting the item no longer reports it twice - replace the re-upload url logic with a plain snapshot: url, method and headers changed by chunk hooks are reset before onSuccessItem, onErrorItem or onCancelItem run, so values the app sets there survive - read the chunk size once per upload so setOptions mid-upload can't skip bytes - removeFromQueue ignores items no longer in the queue, so remove() from a chunk hook with removeAfterUpload doesn't leave the uploader stuck
…urable - chunk retries no longer read the Retry-After header; they wait chunkRetryDelay, doubled per retry - the 30 second cap is now the chunkMaxRetryDelay option (default 30000)
FileUploader and FileItem are back to their previous code, so apps that don't opt in are unaffected. Chunking lives in a ChunkedFileUploader subclass that works with the existing directives. The library no longer retries, delays or restores item fields itself; it reports what happened and lets the app decide: - onBeforeUploadChunk / onSuccessChunk / onErrorChunk hooks - resumeItem(item) continues a failed or cancelled upload from the chunk that didn't complete, so apps can implement their own retries - getChunk(item) returns the current chunk Removed: chunkRetries, chunkRetryDelay, chunkMaxRetryDelay, the retryable status list, restoring url/method/headers, and the special handling of errors thrown by callbacks.
- FileUploader's implementation moves to BaseFileUploader, with form building and request setup extracted into _buildFormData and _openRequest; FileUploader extends it unchanged - ChunkedFileUploader extends BaseFileUploader and reuses both helpers instead of copying them Fixes from review: - resumeItem ignores items no longer in the queue (removeAfterUpload) - cancel from onSuccessChunk resumes at the next chunk; on the last chunk it has no effect since the file is already uploaded - a chunk callback that throws fails the item instead of stalling the queue - docs: per-item retry counter, removeAfterUpload note, cancel and error behaviour
- ChunkedFileUploader extends FileUploader again, so it is a real drop-in (instanceof FileUploader); FileUploader keeps the two extracted helpers _buildFormData and _openRequest and is otherwise unchanged - chunk fields are sent before the file so streaming servers can read them - a throwing chunk callback fails the item only if it is still uploading, and the error is rethrown instead of swallowed - tests: FileUploader request regression spec (passes on the previous FileUploader too), shared fake XHR, field order, rethrow and no-double-report cases - docs: cancel wording, repeated callbacks per resume attempt, rethrow
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds opt-in chunked uploads through a new
ChunkedFileUploaderclass. This is a fresh implementation on the current codebase, building on the idea and API from #977. Thanks @PauloPeres, who is credited as co-author.Closes #880, closes #435.
Apps that don't use the new class are not affected.
FileItemis unchanged. InFileUploader, form building and request setup move unchanged into two protected helpers (_buildFormData,_openRequest) thatChunkedFileUploaderreuses; a new request spec passes on both the old and the newFileUploader.Usage
Behaviour
FileUploader, so it works withng2FileSelect/ng2FileDropand all existing options and callbacks. WithoutchunkSizeit behaves exactly likeFileUploader.chunkIndexandtotalChunksfields. Their names can be changed withchunkIndexParamandtotalChunksParam. WithdisableMultipart, raw chunks are sent with aContent-Rangeheader, unless the app sets one itself.onBeforeUploadChunk(item, chunk)runs before each chunk request.onSuccessChunk(item, chunk, response, status, headers)runs after each successful chunk. Changingitem.url,item.methodoritem.headershere applies to the next chunk.onErrorChunk(item, chunk, response, status, headers)runs when a chunk fails. The item then fails as usual and no more chunks are sent.resumeItem(item)uploads a failed or cancelled item again, starting from the chunk that didn't complete. Failed items must stay in the queue, so retrying needsremoveAfterUploadoff. Each attempt reports the item again (onErrorItem,onCompleteItem,onCompleteAll).item.cancel()stops the remaining chunks, whether called during a request or from a hook. It has no effect once the last chunk has completed, and an item whose chunk failed stays failed.onSuccessItem,onErrorItemandonCompleteItemfire once per file.onBuildItemFormanduploader.responsefire once per chunk request.Testing
chunked-file-uploader.class.spec.ts(41 tests) andfile-uploader-request.spec.ts(7 tests, also passing against the previousFileUploader). The existingFileUploaderspecs pass unchanged. Lint, build, the demo build and all 76 library tests pass.resumeItemafter a 500, and cancel between chunks.