Set up resumable uploads for Android

Upload large media files to FastPix from Android apps with resumable chunked uploads and track the progress.

The FastPix Android Resumable Uploads SDK helps you efficiently upload large files from the browser by splitting them into chunks and also gives you the ability to pause and resume your uploads.



Resumable uploads can be effectively handled through a technique called chunking. This method involves breaking down large files into smaller, more manageable pieces, or “chunks.” Here’s how chunking works:

  1. Divide the file: Large files are split into smaller, manageable chunks (e.g., 16 MB by default).
  2. Upload individually: Each chunk is uploaded separately. If a chunk fails, only that specific chunk needs to be re-uploaded.
  3. Resume capability: If the upload is interrupted, you can resume from the last successfully uploaded chunk instead of starting over.

This approach is important because:

  • It reduces the risk: Uploading smaller chunks minimizes the risk of failure. If a chunk fails to upload due to network issues, only that specific chunk needs to be re-uploaded, not the entire file.
  • Improves performance: Smaller chunks can be uploaded more quickly and efficiently, especially on slower connections, as they require less time to transfer.
  • Easier management: Chunking allows for better tracking of upload progress, making it easier to implement features like pause and resume.


Step 1: Install the Android SDK


Add our repository to your Gradle project

1maven(url ="https://maven.pkg.github.com/FastPix/android-uploads-sdk") {
2 credentials {
3 username = "your_gihub_username"
4 password = "your_github_personal_token"
5 }
6 }
1maven {
2 url "https://maven.pkg.github.com/FastPix/android-uploads-sdk"
3 credentials {
4 username = "your_gihub_username"
5 password = "your_github_personal_token"
6 }
7}

Add the dependency to your app

Add Fastpix’s library to the dependencies block of your app in module level build.gradle file.

1dependencies {
2 implementation("io.fastpix:uploads:1.0.1")
3}
1dependencies {
2 implementation 'io.fastpix:uploads:1.0.1'
3}

Step 2: Create an upload URL

In order to upload a video, you will need a signed upload URL.

To get this signed URL, you’ll need a valid Access Token and Secret Key. See the Authentication Guide for details on retrieving these credentials.

After obtaining your credentials, the next step is to generate a signed URL by calling the Upload Media from Device API. Once you have the signed URL, you’re all set to move forward with integrating the SDK into your app.

The example below demonstrates how to retrieve a signed URL using the Upload Media from Device API. You can either use this example directly or refer to our guide on uploading videos directly for more details.


1private fun getSignedUrl() {
2 val client = OkHttpClient()
3 val mediaType = "application/json; charset=utf-8".toMediaType()
4 // Construct JSON body using JSONObject
5 val requestBodyJson = JSONObject().apply {
6 put("corsOrigin", "*")
7 put("pushMediaSettings", JSONObject().apply {
8 put("metadata", JSONObject().apply {
9 put("key1", "value1")
10 })
11 put("accessPolicy", "public")
12 put("maxResolution", "1080p")
13 put("mediaQuality", "standard")
14 })
15 }
16 val requestBody = requestBodyJson.toString().toRequestBody(mediaType)
17 // Create Authorization header
18 val credentials = "$tokenId:$secretKey"
19 val auth = "Basic " + Base64.encodeToString(credentials.toByteArray(), Base64.NO_WRAP)
20 // Build the HTTP request
21 val request = Request.Builder()
22 .url("https://api.fastpix.com/v1/on-demand/upload")
23 .addHeader("Authorization", auth)
24 .addHeader("Content-Type", "application/json")
25 .post(requestBody)
26 .build()
27 // Execute request
28 client.newCall(request).enqueue(object : Callback {
29 override fun onFailure(call: Call, e: IOException) {
30 LOGGER.log(Level.SEVERE, e.message)
31 }
32 override fun onResponse(call: Call, response: Response) {
33 if (response.isSuccessful) {
34 response.body?.string()?.let {
35 val jsonObject = JSONObject(it)
36 val jsonData = jsonObject.getJSONObject("data")
37 val signedUrl = jsonData.getString("url")
38
39
40
41 // TODO: use signedUrl and uploadId as needed
42 }
43 } else {
44 LOGGER.log(Level.SEVERE, "Upload URL request failed: ${response.code}")
45 }
46 }
47 })
48}
1private void getSignedUrl() {
2 OkHttpClient client = new OkHttpClient();
3
4 // Construct JSON body using JSONObject
5 JSONObject metadata = new JSONObject();
6 JSONObject pushMediaSettings = new JSONObject();
7 JSONObject requestBodyJson = new JSONObject();
8
9 try {
10 metadata.put("key1", "value1");
11 pushMediaSettings.put("metadata", metadata);
12 pushMediaSettings.put("accessPolicy", "public");
13 pushMediaSettings.put("maxResolution", "1080p");
14 pushMediaSettings.put("mediaQuality", "standard");
15
16
17 requestBodyJson.put("corsOrigin", "*");
18 requestBodyJson.put("pushMediaSettings", pushMediaSettings);
19 } catch (JSONException e) {
20 e.printStackTrace();
21 return;
22 }
23
24 MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
25 RequestBody requestBody = RequestBody.create(requestBodyJson.toString(), mediaType);
26
27 // Create Authorization header
28 String credentials = tokenId + ":" + secretKey;
29 String auth = "Basic " + Base64.encodeToString(credentials.getBytes(StandardCharsets.UTF_8), Base64.NO_WRAP);
30
31 // Build the request
32 Request request = new Request.Builder()
33 .url("https://api.fastpix.com/v1/on-demand/upload")
34 .addHeader("Authorization", auth)
35 .addHeader("Content-Type", "application/json")
36 .post(requestBody)
37 .build();
38
39 // Execute the request
40 client.newCall(request).enqueue(new Callback() {
41 @Override
42 public void onFailure(@NonNull Call call, @NonNull IOException e) {
43 Log.e("UPLOAD", "Failed to get signed URL", e);
44 }
45
46 @Override
47 public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
48 if (response.isSuccessful()) {
49 String responseBody = response.body() != null ? response.body().string() : null;
50 if (responseBody != null) {
51 try {
52 JSONObject jsonObject = new JSONObject(responseBody);
53 JSONObject jsonData = jsonObject.getJSONObject("data");
54 String signedUrl = jsonData.getString("url");
55 String uploadId = jsonData.getString("uploadId");
56
57 // TODO: use signedUrl and uploadId as needed
58
59 } catch (JSONException e) {
60 Log.e("UPLOAD", "Failed to parse response", e);
61 }
62 }
63 } else {
64 Log.e("UPLOAD", "Upload URL request failed: " + response.code());
65 }
66 }
67 });
68}

PLEASE NOTE

When making Basic Auth API calls, securely retrieve the username and password from environment variables (.env) or a protected server endpoint to prevent unauthorized access.


In the API response, you will get a signed URL upon successful API request. Next step is to take the signed URL and pass it to the SDK.


Step 3: Start your upload

To perform the upload from your Android app, you can use the FastPixUploadSdk class. At the simplest, you need to build your FastPixUploadSdk via its Builder, then add your listeners and start() the upload.


1val sdk = FastPixUploadSdk.Builder(this)
2 .setFile(file)
3 .setSignedUrl(signedUrl)
4 .setChunkSize(chunkSize * 1024 * 1024)
5 .build()
6sdk.startUpload()
1FastPixUploadSdk sdk = new FastPixUploadSdk.Builder(this)
2 .setFile(file)
3 .setSignedUrl(signedUrl)
4 .setChunkSize(chunkSize * 1024 * 1024)
5 .build();
6sdk.startUpload();

Parameters to use:

This SDK supports the following parameters

ParameterRequired?Description
setSignedUrlYesThe URL endpoint where the file will be uploaded.
setFileYesThe file object that you want to upload (e.g., a video file).
setChunkSizeNoDefines the chunk size in bytes. By default, the SDK splits files into 16 MB chunks. You can customize this (minimum of 5 MB).
callbackNoLets you handle the upload lifecycle events such as progress, completion, and errors.
setMaxRetriesNoSets the number of retry attempts for failed chunk uploads. Defaults to 5.
setRetryDelayNoSets the wait time (in milliseconds) before retrying a failed chunk upload. Defaults to 2000ms.

Monitor the upload progress through lifecycle events

Using the following lifecycle events lets you to build a robust and user-friendly upload experience. By tracking progress in real-time, handling errors proactively, managing chunk retries, and responding to network changes, you can ensure seamless and efficient uploads.

Integrating these event handlers into your application can enhance reliability, optimize performance, and provide users with clear, actionable feedback throughout the upload process.


1class MyUploadCallback : FastPixUploadCallbacks {
2
3 override fun onProgressUpdate(progress: Double) {
4 // Called periodically to report upload progress (0.0 - 100.0)
5 // Example: update a progress bar
6 }
7
8 override fun onSuccess(timiMillis: Long) {
9 // Called when the upload completes successfully
10 // timiMillis indicates how long the upload took
11 }
12
13 override fun onError(error: String, timiMillis: Long) {
14 // Called when an error occurs during upload
15 // error provides the error message
16 // timiMillis indicates how long the upload lasted before failing
17 }
18
19 override fun onNetworkStateChange(isOnline: Boolean) {
20 // Called when the network connectivity changes
21 // isOnline indicates whether the device is currently online or offline
22 }
23
24 override fun onUploadInit() {
25 // Called when the upload process is initialized
26 // Use this to show an initial loading state or setup UI
27 }
28
29 override fun onAbort() {
30 // Called when the upload is manually aborted
31 // Use this to clean up UI or notify the user
32 }
33
34 override fun onChunkHandled(
35 totalChunks: Int,
36 filSizeInBytes: Long,
37 currentChunk: Int,
38 currentChunkSizeInBytes: Long
39 ) {
40 // Called after a chunk is successfully uploaded
41 // totalChunks: total number of chunks to upload
42 // filSizeInBytes: total file size
43 // currentChunk: index of the currently uploaded chunk
44 // currentChunkSizeInBytes: size of the uploaded chunk
45 }
46
47 override fun onChunkUploadingFailed(
48 failedChunkRetries: Int,
49 chunkCount: Int,
50 chunkSize: Long
51 ) {
52 // Called when a chunk fails to upload after retry attempts
53 // failedChunkRetries: number of retries attempted for the chunk
54 // chunkCount: index of the failed chunk
55 // chunkSize: size of the failed chunk
56 }
57
58 override fun onPauseUploading() {
59 // Called when the upload is paused
60 // Use this to reflect paused state in UI
61 }
62
63 override fun onResumeUploading() {
64 // Called when the upload resumes after being paused
65 // Use this to resume UI indicators or timers
66 }
67}
1public class MyUploadCallback implements FastPixUploadCallbacks {
2
3 @Override
4 public void onProgressUpdate(double progress) {
5 // Called periodically to report upload progress (0.0 - 100.0)
6 // Example: update a progress bar
7 }
8
9 @Override
10 public void onSuccess(long timiMillis) {
11 // Called when the upload completes successfully
12 // timiMillis indicates how long the upload took
13 }
14
15 @Override
16 public void onError(String error, long timiMillis) {
17 // Called when an error occurs during upload
18 // error provides the error message
19 // timiMillis indicates how long the upload lasted before failing
20 }
21
22 @Override
23 public void onNetworkStateChange(boolean isOnline) {
24 // Called when the network connectivity changes
25 // isOnline indicates whether the device is currently online or offline
26 }
27
28 @Override
29 public void onUploadInit() {
30 // Called when the upload process is initialized
31 // Use this to show an initial loading state or setup UI
32 }
33
34 @Override
35 public void onAbort() {
36 // Called when the upload is manually aborted
37 // Use this to clean up UI or notify the user
38 }
39
40 @Override
41 public void onChunkHandled(int totalChunks, long filSizeInBytes, int currentChunk, long currentChunkSizeInBytes) {
42 // Called after a chunk is successfully uploaded
43 // totalChunks: total number of chunks to upload
44 // filSizeInBytes: total file size
45 // currentChunk: index of the currently uploaded chunk
46 // currentChunkSizeInBytes: size of the uploaded chunk
47 }
48
49 @Override
50 public void onChunkUploadingFailed(int failedChunkRetries, int chunkCount, long chunkSize) {
51 // Called when a chunk fails to upload after retry attempts
52 // failedChunkRetries: number of retries attempted for the chunk
53 // chunkCount: index of the failed chunk
54 // chunkSize: size of the failed chunk
55 }
56
57 @Override
58 public void onPauseUploading() {
59 // Called when the upload is paused
60 // Use this to reflect paused state in UI
61 }
62
63 @Override
64 public void onResumeUploading() {
65 // Called when the upload resumes after being paused
66 // Use this to resume UI indicators or timers
67 }
68}

Manage video uploads

You can control the upload lifecycle with the following methods:


Pause an upload:

1sdk.pauseUploading()

Resume an upload:

1sdk.resumeUploading()

Abort an upload:

sdk.abort()

Usage example of Android uploads SDK

The following examples give an overview of integrating the FastPix Android Uploads SDK into your project, enabling you to build a fully customized upload interface. By making use of the SDK’s lifecycle events and configurable attributes, you can enhance functionality and optimize the upload experience.


1class UploadActivity : AppCompatActivity(), FastPixUploadCallbacks {
2
3 private lateinit var sdk: FastPixUploadSdk
4
5 override fun onCreate(savedInstanceState: Bundle?) {
6 super.onCreate(savedInstanceState)
7
8 val file = File(filesDir, "your-video.mp4")
9 val signedUrl = "https://your-signed-upload-url" // Replace with actual signed URL
10 val chunkSize = 5 // Chunk size in MB
11
12 sdk = FastPixUploadSdk.Builder(this)
13 .setFile(file)
14 .setSignedUrl(signedUrl)
15 .setChunkSize(chunkSize * 1024 * 1024) // Convert MB to bytes
16 .setMaxRetries(3) // Optional: Number of retries for failed chunks
17 .setRetryDelay(2000) // Optional: Delay between retries in milliseconds
18 .callback(this) // Set this activity as the callback handler
19 .build()
20
21 sdk.startUpload() // Start the upload
22 }
23
24 // === FastPixUploadCallbacks Implementation ===
25
26 override fun onProgressUpdate(progress: Double) {
27 // Called periodically to report upload progress (0.0 - 100.0)
28 Log.d("Upload", "Progress: $progress%")
29 }
30
31 override fun onSuccess(timiMillis: Long) {
32 // Called when the upload completes successfully
33 Log.d("Upload", "Upload completed in $timiMillis ms")
34 }
35
36 override fun onError(error: String, timiMillis: Long) {
37 // Called when an error occurs during upload
38 Log.e("Upload", "Error: $error after $timiMillis ms")
39 }
40
41 override fun onNetworkStateChange(isOnline: Boolean) {
42 // Called when the network connectivity changes
43 Log.d("Upload", if (isOnline) "Back online" else "Offline")
44 }
45
46 override fun onUploadInit() {
47 // Called when the upload process is initialized
48 Log.d("Upload", "Upload initialized")
49 }
50
51 override fun onAbort() {
52 // Called when the upload is manually aborted
53 Log.d("Upload", "Upload aborted by user")
54 }
55
56 override fun onChunkHandled(
57 totalChunks: Int,
58 filSizeInBytes: Long,
59 currentChunk: Int,
60 currentChunkSizeInBytes: Long
61 ) {
62 // Called after a chunk is successfully uploaded
63 Log.d("Upload", "Uploaded chunk $currentChunk/$totalChunks")
64 }
65
66 override fun onChunkUploadingFailed(
67 failedChunkRetries: Int,
68 chunkCount: Int,
69 chunkSize: Long
70 ) {
71 // Called when a chunk fails after all retry attempts
72 Log.e("Upload", "Chunk $chunkCount failed after $failedChunkRetries retries")
73 }
74
75 override fun onPauseUploading() {
76 // Called when the upload is paused
77 Log.d("Upload", "Upload paused")
78 }
79
80 override fun onResumeUploading() {
81 // Called when the upload resumes
82 Log.d("Upload", "Upload resumed")
83 }
84}
1class UploadActivity : AppCompatActivity(), FastPixUploadCallbacks {
2
3 private lateinit var sdk: FastPixUploadSdk
4
5 override fun onCreate(savedInstanceState: Bundle?) {
6 super.onCreate(savedInstanceState)
7
8 val file = File(filesDir, "your-video.mp4")
9 val signedUrl = "https://your-signed-upload-url" // Replace with actual signed URL
10 val chunkSize = 5 // Chunk size in MB
11
12 sdk = FastPixUploadSdk.Builder(this)
13 .setFile(file)
14 .setSignedUrl(signedUrl)
15 .setChunkSize(chunkSize * 1024 * 1024) // Convert MB to bytes
16 .setMaxRetries(3) // Optional: Number of retries for failed chunks
17 .setRetryDelay(2000) // Optional: Delay between retries in milliseconds
18 .callback(this) // Set this activity as the callback handler
19 .build()
20
21 sdk.startUpload() // Start the upload
22 }
23
24 // === FastPixUploadCallbacks Implementation ===
25
26 override fun onProgressUpdate(progress: Double) {
27 // Called periodically to report upload progress (0.0 - 100.0)
28 Log.d("Upload", "Progress: $progress%")
29 }
30
31 override fun onSuccess(timiMillis: Long) {
32 // Called when the upload completes successfully
33 Log.d("Upload", "Upload completed in $timiMillis ms")
34 }
35
36 override fun onError(error: String, timiMillis: Long) {
37 // Called when an error occurs during upload
38 Log.e("Upload", "Error: $error after $timiMillis ms")
39 }
40
41 override fun onNetworkStateChange(isOnline: Boolean) {
42 // Called when the network connectivity changes
43 Log.d("Upload", if (isOnline) "Back online" else "Offline")
44 }
45
46 override fun onUploadInit() {
47 // Called when the upload process is initialized
48 Log.d("Upload", "Upload initialized")
49 }
50
51 override fun onAbort() {
52 // Called when the upload is manually aborted
53 Log.d("Upload", "Upload aborted by user")
54 }
55
56 override fun onChunkHandled(
57 totalChunks: Int,
58 filSizeInBytes: Long,
59 currentChunk: Int,
60 currentChunkSizeInBytes: Long
61 ) {
62 // Called after a chunk is successfully uploaded
63 Log.d("Upload", "Uploaded chunk $currentChunk/$totalChunks")
64 }
65
66 override fun onChunkUploadingFailed(
67 failedChunkRetries: Int,
68 chunkCount: Int,
69 chunkSize: Long
70 ) {
71 // Called when a chunk fails after all retry attempts
72 Log.e("Upload", "Chunk $chunkCount failed after $failedChunkRetries retries")
73 }
74
75 override fun onPauseUploading() {
76 // Called when the upload is paused
77 Log.d("Upload", "Upload paused")
78 }
79
80 override fun onResumeUploading() {
81 // Called when the upload resumes
82 Log.d("Upload", "Upload resumed")
83 }
84}



Changelog

All notable changes to the Upload SDK for android will be documented below.


Current version

[2.0.0]

A full rewrite of the upload engine for spec-compliant, production-grade GCS resumable uploads. Breaking: the public API has changed — see the migration table in the README.

Added

  • New public API under io.fastpix.uploads:
    • FastPixUploader (replaces FastPixUploadSdk) with a fluent Builder and start() / pause() / resume() / cancel() methods.
    • UploadListener (replaces FastPixUploadCallbacks) with no-op defaults — override only what you need. New callbacks: onStateChange(UploadState), onPrepared(...), onChunkUploaded(...), onRetryScheduled(...), onCancelled(...).
    • UploadState enum (IDLE, PREPARING, UPLOADING, PAUSED, RETRYING, NETWORK_LOST, QUERYING_STATUS, COMPLETED, FAILED, CANCELLED) for explicit lifecycle modelling.
    • UploadError sealed class with typed variants: InvalidConfiguration, FileNotFound, FileNotReadable, FileEmpty, FileReadFailure, NetworkFailure, SessionExpired (HTTP 410), ClientError(code), ServerError(code), RetryLimitExceeded, UnexpectedResponse.
  • GCS spec compliance:
    • Chunk PUTs with Content-Range: bytes start-end/total; non-final chunk size enforced as a multiple of 256 KiB at build time.
    • Server-authoritative resume: parses the Range header from 308 Resume Incomplete and resumes from last + 1. Handles 308 without a Range header (resume from byte 0) per spec.
    • Always issues a status query (PUT with Content-Range: bytes */TOTAL, empty body) before resuming after pause, network loss, or transient failure — never assumes how much the server has.
    • HTTP 410 → UploadError.SessionExpired. Retryable: 408, 429, 5xx. Fatal: other 4xx.
  • Smooth, monotonic progress. Updates fire as each chunk streams (no longer only at chunk boundaries), throttled to one event per integer-percent change. A CAS-guarded high-water mark ensures progress never regresses on retry.
  • Explicit upload state machine with validated transitions. Structurally impossible to send a chunk PUT after pause/retry/network-loss without first going through QUERYING_STATUS.
  • Single-threaded engine. All state mutations serialised on one executor; OkHttp callbacks, network events, consumer commands, and retry timers all funnel through it. No race conditions.
  • Multi-transport network awareness. Tracks the active set of networks with INTERNET capability; only signals offline when all transports drop. Transient WiFi/cellular handover events no longer trip false NETWORK_LOST.
  • Configurable retry policy. Full-jitter exponential backoff (retryBaseDelay, retryMaxDelay), bounded by maxRetries.
  • Main-thread callback dispatch by default. Listener calls land on the main looper; consumers no longer need runOnUiThread wrappers. Override via Builder.callbackExecutor(Executor).
  • Optional HTTP logging via Builder.debugLogging(true). Off by default — release builds no longer leak signed session URIs to logcat.
  • JUnit unit tests for GcsResumableProtocol, UploadStateMachine, RetryPolicy, and CallbackDispatcher (47 tests total).

Fixed

  • Retries no longer silently disabled after the first successful chunk. The retry executor is now permanent for the upload’s lifetime; previously a CoroutineScope.cancel() killed it after chunk 1, causing later failures to hang forever.
  • Network failures are now routed through the retry path. Previously any IOException (broken pipe, DNS hiccup, TLS reset, OkHttp cancel) terminated the upload with onError. Now classified, backed off, and resumed via status query.
  • onSuccess, onFailure, and onCancelled now actually fire. A “defense in depth” terminated-flag silently dropped the terminal callback itself. Removed.
  • cancel() no longer double-fires onError + onCancelled. OkHttp call cancellation is now correctly distinguished from real failures via a generation counter.
  • pause() no longer leaks as onError. Intentional cancellations are detected in onFailure and suppressed.
  • NetworkCallback no longer leaks across uploads. Per-uploader registration with explicit unregisterNetworkCallback on terminal.
  • Working Wi-Fi no longer falsely reported as NETWORK_LOST. Dropped the NET_CAPABILITY_VALIDATED requirement, which is gated on a probe to Google’s connectivitycheck endpoint and is missing for the first few seconds of a fresh connection (and indefinitely on networks where that endpoint is blocked, e.g. corporate Wi-Fi).
  • Transient losses during WiFi/cellular handover no longer trigger NETWORK_LOST. Network state is now derived from the set of matching networks; offline is signalled only when all transports drop.
  • File reads no longer silently misalign on large files. RandomAccessFile.seek() replaces InputStream.skip(), which was allowed to skip fewer bytes than requested.
  • OkHttp no longer silently re-PUTs bodies on connection failure. retryOnConnectionFailure(false) lets the upload engine own all retry semantics.
  • Public commands after terminal state no longer crash. cancel() called twice, late OkHttp callbacks, and late connectivity events post-teardown now silently no-op instead of throwing RejectedExecutionException.

Changed

  • Minimum SDK bumped from API 21 to API 24.
  • Default chunk size changed from 16 MiB to 8 MiB (the GCS-recommended value).
  • Method renames (see migration table in README): setSignedUrlsessionUri, setFilefile, setChunkSizechunkSize, setMaxRetriesmaxRetries, setRetryDelayretryBaseDelay + retryMaxDelay, callbacklistener, startUploadstart, pauseUploadingpause, resumeUploadingresume, abortcancel.
  • Errors: UploadExceptions and its subclasses replaced with the UploadError sealed hierarchy.

Removed

  • FastPixUploadSdk, FastPixUploadCallbacks, UploadExceptions, StreamingFileRequestBody, RetryHelper, NetworkHandler, UploadEventType.

Previous version

v1.0.1

  • Implemented support for Google Cloud Storage resumable uploads and chunked client uploads.
  • Added retry mechanism with exponential backoff for GCS upload failures based on retryable status codes.
  • Enabled support for user-provided signed URLs, allowing resumable uploads to work with externally generated session URIs.
  • Updated the API endpoint from https://v1.fastpix.io/on-demand/uploads to https://api.fastpix.com/v1/on-demand/upload for obtaining signed URLs.

v1.0.0

Features:

  • Chunking: Files are automatically split into chunks (default chunk size is 16MB).
  • Pause and Resume: Allows temporarily pausing the upload and resuming after a while.
  • Retry: Uploads might fail due to temporary network failures. Individual chunks are retried for 5 times with exponential backoff to recover automatically from such failures.
  • Lifecycle Event Listeners: Provides real-time feedback through various upload lifecycle events.
  • Error Handling: Comprehensive error management to notify users of issues during uploads.
  • Customizability: Options to customize chunk size and retry attempts.