Skip to content

Commit f2ce24b

Browse files
committed
feat: add upload progress callback and abort signal support
1 parent aabfd00 commit f2ce24b

File tree

3 files changed

+44
-15
lines changed

3 files changed

+44
-15
lines changed

src/constants/errorMessages.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ export default {
1515
help: "",
1616
},
1717
INVALID_UPLOAD_OPTIONS: { message: "Invalid uploadOptions parameter", help: "" },
18-
MISSING_SIGNATURE: { message: "Missing signature for upload. The SDK expects token, signature and expire for authentication.", help: ""},
19-
MISSING_TOKEN: { message: "Missing token for upload. The SDK expects token, signature and expire for authentication.", help: ""},
20-
MISSING_EXPIRE: { message: "Missing expire for upload. The SDK expects token, signature and expire for authentication.", help: ""},
21-
INVALID_TRANSFORMATION: { message: "Invalid transformation parameter. Please include at least pre, post, or both.", help: ""},
22-
INVALID_PRE_TRANSFORMATION: { message: "Invalid pre transformation parameter.", help: ""},
23-
INVALID_POST_TRANSFORMATION: { message: "Invalid post transformation parameter.", help: ""},
18+
MISSING_SIGNATURE: { message: "Missing signature for upload. The SDK expects token, signature and expire for authentication.", help: "" },
19+
MISSING_TOKEN: { message: "Missing token for upload. The SDK expects token, signature and expire for authentication.", help: "" },
20+
MISSING_EXPIRE: { message: "Missing expire for upload. The SDK expects token, signature and expire for authentication.", help: "" },
21+
INVALID_TRANSFORMATION: { message: "Invalid transformation parameter. Please include at least pre, post, or both.", help: "" },
22+
INVALID_PRE_TRANSFORMATION: { message: "Invalid pre transformation parameter.", help: "" },
23+
INVALID_POST_TRANSFORMATION: { message: "Invalid post transformation parameter.", help: "" },
24+
UPLOAD_ABORTED: { message: "Request aborted by the user", help: "" },
2425
};

src/interfaces/UploadOptions.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,5 +145,15 @@ export interface UploadOptions {
145145
/**
146146
* Optional `checks` parameters can be used to run server-side checks before files are uploaded to the Media Library.
147147
*/
148-
checks?: string
148+
checks?: string;
149+
150+
/**
151+
* Optional callback function that will be called with the progress event when the file is being uploaded.
152+
*/
153+
onProgress?: (event: ProgressEvent) => void;
154+
155+
/**
156+
* Optional AbortSignal object that can be used to abort the upload request
157+
*/
158+
signal?: AbortSignal;
149159
}

src/upload/index.ts

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import errorMessages from "../constants/errorMessages";
2-
import respond from "../utils/respond";
3-
import { request } from "../utils/request";
42
import { ImageKitOptions, UploadOptions, UploadResponse } from "../interfaces";
3+
import { request } from "../utils/request";
4+
import respond from "../utils/respond";
55

66
export const upload = (
77
xhr: XMLHttpRequest,
@@ -24,17 +24,17 @@ export const upload = (
2424
return;
2525
}
2626

27-
if(!uploadOptions.token) {
27+
if (!uploadOptions.token) {
2828
respond(true, errorMessages.MISSING_TOKEN, callback)
2929
return
3030
}
3131

32-
if(!uploadOptions.signature) {
32+
if (!uploadOptions.signature) {
3333
respond(true, errorMessages.MISSING_SIGNATURE, callback)
3434
return
3535
}
3636

37-
if(!uploadOptions.expire) {
37+
if (!uploadOptions.expire) {
3838
respond(true, errorMessages.MISSING_EXPIRE, callback)
3939
return
4040
}
@@ -73,7 +73,7 @@ export const upload = (
7373
if (key === "file" && typeof uploadOptions.file != "string") {
7474
formData.append('file', uploadOptions.file, String(uploadOptions.fileName));
7575
} else if (key === "tags" && Array.isArray(uploadOptions.tags)) {
76-
formData.append('tags', uploadOptions.tags.join(","));
76+
formData.append('tags', uploadOptions.tags.join(","));
7777
} else if (key === 'signature') {
7878
formData.append("signature", uploadOptions.signature);
7979
} else if (key === 'expire') {
@@ -87,18 +87,36 @@ export const upload = (
8787
} else if (key === "customMetadata" && typeof uploadOptions.customMetadata === "object" &&
8888
!Array.isArray(uploadOptions.customMetadata) && uploadOptions.customMetadata !== null) {
8989
formData.append('customMetadata', JSON.stringify(uploadOptions.customMetadata));
90-
} else if(key === "transformation" && typeof uploadOptions.transformation === "object" &&
90+
} else if (key === "transformation" && typeof uploadOptions.transformation === "object" &&
9191
uploadOptions.transformation !== null) {
9292
formData.append(key, JSON.stringify(uploadOptions.transformation));
9393
} else if (key === 'checks' && uploadOptions.checks) {
9494
formData.append("checks", uploadOptions.checks);
95-
} else if(uploadOptions[key] !== undefined) {
95+
} else if (uploadOptions[key] !== undefined) {
9696
formData.append(key, String(uploadOptions[key]));
9797
}
9898
}
9999
}
100100

101101
formData.append("publicKey", options.publicKey);
102102

103+
if (uploadOptions.onProgress) {
104+
xhr.upload.onprogress = function (event: ProgressEvent) {
105+
if (uploadOptions.onProgress) uploadOptions.onProgress(event)
106+
};
107+
}
108+
109+
if (uploadOptions.signal && uploadOptions.signal) {
110+
if (uploadOptions.signal.aborted) { // If the signal is already aborted, return immediately with the reason
111+
respond(true, uploadOptions.signal.reason ?? errorMessages.UPLOAD_ABORTED, callback);
112+
return;
113+
}
114+
// If the signal is not already aborted, add an event listener to abort the request when the signal is aborted
115+
uploadOptions.signal.addEventListener("abort", function () {
116+
xhr.abort();
117+
respond(true, this.reason, callback);
118+
});
119+
}
120+
103121
request(xhr, formData, callback);
104122
};

0 commit comments

Comments
 (0)