@uploadcare/upload-client 6.0.1-alpha.0 → 6.0.1-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.browser.js +185 -126
- package/dist/index.d.ts +62 -55
- package/dist/index.node.js +186 -127
- package/dist/index.react-native.js +220 -148
- package/package.json +1 -1
|
@@ -157,6 +157,26 @@ const poll = ({ check, interval = DEFAULT_INTERVAL, timeout, signal }) => new Pr
|
|
|
157
157
|
tickTimeoutId = setTimeout(tick, 0);
|
|
158
158
|
});
|
|
159
159
|
|
|
160
|
+
/*
|
|
161
|
+
Settings for future support:
|
|
162
|
+
parallelDirectUploads: 10,
|
|
163
|
+
*/
|
|
164
|
+
const defaultSettings = {
|
|
165
|
+
baseCDN: 'https://ucarecdn.com',
|
|
166
|
+
baseURL: 'https://upload.uploadcare.com',
|
|
167
|
+
maxContentLength: 50 * 1024 * 1024,
|
|
168
|
+
retryThrottledRequestMaxTimes: 1,
|
|
169
|
+
retryNetworkErrorMaxTimes: 3,
|
|
170
|
+
multipartMinFileSize: 25 * 1024 * 1024,
|
|
171
|
+
multipartChunkSize: 5 * 1024 * 1024,
|
|
172
|
+
multipartMinLastPartSize: 1024 * 1024,
|
|
173
|
+
maxConcurrentRequests: 4,
|
|
174
|
+
pollingTimeoutMilliseconds: 10000,
|
|
175
|
+
pusherKey: '79ae88bd931ea68464d9'
|
|
176
|
+
};
|
|
177
|
+
const defaultContentType = 'application/octet-stream';
|
|
178
|
+
const defaultFilename = 'original';
|
|
179
|
+
|
|
160
180
|
const request = ({ method, url, data, headers = {}, signal, onProgress }) => new Promise((resolve, reject) => {
|
|
161
181
|
const xhr = new XMLHttpRequest();
|
|
162
182
|
const requestMethod = method?.toUpperCase() || 'GET';
|
|
@@ -249,45 +269,42 @@ const request = ({ method, url, data, headers = {}, signal, onProgress }) => new
|
|
|
249
269
|
}
|
|
250
270
|
});
|
|
251
271
|
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
if (typeof file === 'string' && file.startsWith('file:')) {
|
|
255
|
-
return { uri: file, name };
|
|
256
|
-
}
|
|
257
|
-
const uri = URL.createObjectURL(file);
|
|
258
|
-
const type = file.type;
|
|
259
|
-
return { uri, name, type };
|
|
272
|
+
const isBlob = (data) => {
|
|
273
|
+
return typeof Blob !== 'undefined' && data instanceof Blob;
|
|
260
274
|
};
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* FileData type guard.
|
|
265
|
-
*/
|
|
266
|
-
const isFileData = (data) => {
|
|
267
|
-
return (data !== undefined &&
|
|
268
|
-
((typeof Blob !== 'undefined' && data instanceof Blob) ||
|
|
269
|
-
(typeof File !== 'undefined' && data instanceof File) ||
|
|
270
|
-
(typeof Buffer !== 'undefined' && data instanceof Buffer) ||
|
|
271
|
-
(typeof data === 'string' && data.startsWith('file:'))));
|
|
275
|
+
const isFile = (data) => {
|
|
276
|
+
return typeof File !== 'undefined' && data instanceof File;
|
|
272
277
|
};
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
*/
|
|
276
|
-
const isUuid = (data) => {
|
|
277
|
-
const UUID_REGEX = '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}';
|
|
278
|
-
const regExp = new RegExp(UUID_REGEX);
|
|
279
|
-
return !isFileData(data) && regExp.test(data);
|
|
278
|
+
const isBuffer = (data) => {
|
|
279
|
+
return typeof Buffer !== 'undefined' && data instanceof Buffer;
|
|
280
280
|
};
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
return
|
|
281
|
+
const isReactNativeAsset = (data) => {
|
|
282
|
+
return (!!data &&
|
|
283
|
+
typeof data === 'object' &&
|
|
284
|
+
!Array.isArray(data) &&
|
|
285
|
+
'uri' in data &&
|
|
286
|
+
typeof data.uri === 'string');
|
|
287
|
+
};
|
|
288
|
+
const isFileData = (data) => {
|
|
289
|
+
return (isBlob(data) || isFile(data) || isBuffer(data) || isReactNativeAsset(data));
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
const getFileOptions = () => [];
|
|
293
|
+
const transformFile = (file, name, contentType) => {
|
|
294
|
+
if (isReactNativeAsset(file)) {
|
|
295
|
+
return {
|
|
296
|
+
uri: file.uri,
|
|
297
|
+
name: file.name || name,
|
|
298
|
+
type: file.type || contentType
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
if (isBlob(file)) {
|
|
302
|
+
const uri = URL.createObjectURL(file);
|
|
303
|
+
return { uri, name: name, type: file.type || contentType };
|
|
304
|
+
}
|
|
305
|
+
throw new Error(`Unsupported file type: ${file}`);
|
|
290
306
|
};
|
|
307
|
+
var getFormData = () => new FormData();
|
|
291
308
|
|
|
292
309
|
const isSimpleValue = (value) => {
|
|
293
310
|
return (typeof value === 'string' ||
|
|
@@ -304,8 +321,8 @@ const isFileValue = (value) => !!value &&
|
|
|
304
321
|
function collectParams(params, inputKey, inputValue) {
|
|
305
322
|
if (isFileValue(inputValue)) {
|
|
306
323
|
const { name, contentType } = inputValue;
|
|
307
|
-
const file = transformFile(inputValue.data, name); // lgtm [js/superfluous-trailing-arguments]
|
|
308
|
-
const options = getFileOptions(
|
|
324
|
+
const file = transformFile(inputValue.data, name, contentType); // lgtm [js/superfluous-trailing-arguments]
|
|
325
|
+
const options = getFileOptions();
|
|
309
326
|
params.push([inputKey, file, ...options]);
|
|
310
327
|
}
|
|
311
328
|
else if (isObjectValue(inputValue)) {
|
|
@@ -337,6 +354,19 @@ function buildFormData(options) {
|
|
|
337
354
|
return formData;
|
|
338
355
|
}
|
|
339
356
|
|
|
357
|
+
class UploadClientError extends Error {
|
|
358
|
+
constructor(message, code, request, response, headers) {
|
|
359
|
+
super();
|
|
360
|
+
this.name = 'UploadClientError';
|
|
361
|
+
this.message = message;
|
|
362
|
+
this.code = code;
|
|
363
|
+
this.request = request;
|
|
364
|
+
this.response = response;
|
|
365
|
+
this.headers = headers;
|
|
366
|
+
Object.setPrototypeOf(this, UploadClientError.prototype);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
340
370
|
const buildSearchParams = (query) => {
|
|
341
371
|
const searchParams = new URLSearchParams();
|
|
342
372
|
for (const [key, value] of Object.entries(query)) {
|
|
@@ -368,26 +398,6 @@ const getUrl = (base, path, query) => {
|
|
|
368
398
|
return url.toString();
|
|
369
399
|
};
|
|
370
400
|
|
|
371
|
-
/*
|
|
372
|
-
Settings for future support:
|
|
373
|
-
parallelDirectUploads: 10,
|
|
374
|
-
*/
|
|
375
|
-
const defaultSettings = {
|
|
376
|
-
baseCDN: 'https://ucarecdn.com',
|
|
377
|
-
baseURL: 'https://upload.uploadcare.com',
|
|
378
|
-
maxContentLength: 50 * 1024 * 1024,
|
|
379
|
-
retryThrottledRequestMaxTimes: 1,
|
|
380
|
-
retryNetworkErrorMaxTimes: 3,
|
|
381
|
-
multipartMinFileSize: 25 * 1024 * 1024,
|
|
382
|
-
multipartChunkSize: 5 * 1024 * 1024,
|
|
383
|
-
multipartMinLastPartSize: 1024 * 1024,
|
|
384
|
-
maxConcurrentRequests: 4,
|
|
385
|
-
pollingTimeoutMilliseconds: 10000,
|
|
386
|
-
pusherKey: '79ae88bd931ea68464d9'
|
|
387
|
-
};
|
|
388
|
-
const defaultContentType = 'application/octet-stream';
|
|
389
|
-
const defaultFilename = 'original';
|
|
390
|
-
|
|
391
401
|
var version = '6.0.0';
|
|
392
402
|
|
|
393
403
|
const LIBRARY_NAME = 'UploadcareUploadClient';
|
|
@@ -400,19 +410,6 @@ function getUserAgent(options) {
|
|
|
400
410
|
});
|
|
401
411
|
}
|
|
402
412
|
|
|
403
|
-
class UploadClientError extends Error {
|
|
404
|
-
constructor(message, code, request, response, headers) {
|
|
405
|
-
super();
|
|
406
|
-
this.name = 'UploadClientError';
|
|
407
|
-
this.message = message;
|
|
408
|
-
this.code = code;
|
|
409
|
-
this.request = request;
|
|
410
|
-
this.response = response;
|
|
411
|
-
this.headers = headers;
|
|
412
|
-
Object.setPrototypeOf(this, UploadClientError.prototype);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
413
|
const REQUEST_WAS_THROTTLED_CODE = 'RequestThrottledError';
|
|
417
414
|
const DEFAULT_RETRY_AFTER_TIMEOUT = 15000;
|
|
418
415
|
const DEFAULT_NETWORK_ERROR_TIMEOUT = 1000;
|
|
@@ -443,6 +440,36 @@ function retryIfFailed(fn, options) {
|
|
|
443
440
|
}));
|
|
444
441
|
}
|
|
445
442
|
|
|
443
|
+
const getContentType = (file) => {
|
|
444
|
+
let contentType = '';
|
|
445
|
+
if (isBlob(file) || isFile(file) || isReactNativeAsset(file)) {
|
|
446
|
+
contentType = file.type;
|
|
447
|
+
}
|
|
448
|
+
if (contentType) {
|
|
449
|
+
return contentType;
|
|
450
|
+
}
|
|
451
|
+
console.warn(`Cannot determine content type for ${file}. Using default content type: ${defaultContentType}`);
|
|
452
|
+
return defaultContentType;
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
const getFilename = (file) => {
|
|
456
|
+
let filename = '';
|
|
457
|
+
if (isBlob(file) || isBuffer(file)) {
|
|
458
|
+
filename = '';
|
|
459
|
+
}
|
|
460
|
+
else if (isFile(file) && file.name) {
|
|
461
|
+
filename = file.name;
|
|
462
|
+
}
|
|
463
|
+
else if (isReactNativeAsset(file) && file.name) {
|
|
464
|
+
filename = file.name;
|
|
465
|
+
}
|
|
466
|
+
if (filename) {
|
|
467
|
+
return filename;
|
|
468
|
+
}
|
|
469
|
+
console.warn(`Cannot determine filename for ${file}. Using default filename: ${defaultFilename}`);
|
|
470
|
+
return defaultFilename;
|
|
471
|
+
};
|
|
472
|
+
|
|
446
473
|
function getStoreValue(store) {
|
|
447
474
|
return typeof store === 'undefined' ? 'auto' : store ? '1' : '0';
|
|
448
475
|
}
|
|
@@ -463,8 +490,8 @@ function base(file, { publicKey, fileName, contentType, baseURL = defaultSetting
|
|
|
463
490
|
data: buildFormData({
|
|
464
491
|
file: {
|
|
465
492
|
data: file,
|
|
466
|
-
name: fileName
|
|
467
|
-
contentType
|
|
493
|
+
name: fileName || getFilename(file),
|
|
494
|
+
contentType: contentType || getContentType(file)
|
|
468
495
|
},
|
|
469
496
|
UPLOADCARE_PUB_KEY: publicKey,
|
|
470
497
|
UPLOADCARE_STORE: getStoreValue(store),
|
|
@@ -662,9 +689,9 @@ function multipartStart(size, { publicKey, contentType, fileName, multipartChunk
|
|
|
662
689
|
'X-UC-User-Agent': getUserAgent({ publicKey, integration, userAgent })
|
|
663
690
|
},
|
|
664
691
|
data: buildFormData({
|
|
665
|
-
filename: fileName
|
|
692
|
+
filename: fileName || defaultFilename,
|
|
666
693
|
size: size,
|
|
667
|
-
content_type: contentType
|
|
694
|
+
content_type: contentType || defaultContentType,
|
|
668
695
|
part_size: multipartChunkSize,
|
|
669
696
|
UPLOADCARE_STORE: getStoreValue(store),
|
|
670
697
|
UPLOADCARE_PUB_KEY: publicKey,
|
|
@@ -741,6 +768,28 @@ function multipartComplete(uuid, { publicKey, baseURL = defaultSettings.baseURL,
|
|
|
741
768
|
}), { retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes });
|
|
742
769
|
}
|
|
743
770
|
|
|
771
|
+
function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, signal, onProgress }) {
|
|
772
|
+
return poll({
|
|
773
|
+
check: (signal) => info(file, {
|
|
774
|
+
publicKey,
|
|
775
|
+
baseURL,
|
|
776
|
+
signal,
|
|
777
|
+
source,
|
|
778
|
+
integration,
|
|
779
|
+
userAgent,
|
|
780
|
+
retryThrottledRequestMaxTimes,
|
|
781
|
+
retryNetworkErrorMaxTimes
|
|
782
|
+
}).then((response) => {
|
|
783
|
+
if (response.isReady) {
|
|
784
|
+
return response;
|
|
785
|
+
}
|
|
786
|
+
onProgress && onProgress({ isComputable: true, value: 1 });
|
|
787
|
+
return false;
|
|
788
|
+
}),
|
|
789
|
+
signal
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
|
|
744
793
|
class UploadcareFile {
|
|
745
794
|
constructor(fileInfo, { baseCDN, fileName }) {
|
|
746
795
|
this.name = null;
|
|
@@ -778,28 +827,6 @@ class UploadcareFile {
|
|
|
778
827
|
}
|
|
779
828
|
}
|
|
780
829
|
|
|
781
|
-
function isReadyPoll({ file, publicKey, baseURL, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, signal, onProgress }) {
|
|
782
|
-
return poll({
|
|
783
|
-
check: (signal) => info(file, {
|
|
784
|
-
publicKey,
|
|
785
|
-
baseURL,
|
|
786
|
-
signal,
|
|
787
|
-
source,
|
|
788
|
-
integration,
|
|
789
|
-
userAgent,
|
|
790
|
-
retryThrottledRequestMaxTimes,
|
|
791
|
-
retryNetworkErrorMaxTimes
|
|
792
|
-
}).then((response) => {
|
|
793
|
-
if (response.isReady) {
|
|
794
|
-
return response;
|
|
795
|
-
}
|
|
796
|
-
onProgress && onProgress({ isComputable: true, value: 1 });
|
|
797
|
-
return false;
|
|
798
|
-
}),
|
|
799
|
-
signal
|
|
800
|
-
});
|
|
801
|
-
}
|
|
802
|
-
|
|
803
830
|
const uploadDirect = (file, { publicKey, fileName, baseURL, secureSignature, secureExpire, store, contentType, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, baseCDN, metadata }) => {
|
|
804
831
|
return base(file, {
|
|
805
832
|
publicKey,
|
|
@@ -835,6 +862,29 @@ const uploadDirect = (file, { publicKey, fileName, baseURL, secureSignature, sec
|
|
|
835
862
|
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
|
|
836
863
|
};
|
|
837
864
|
|
|
865
|
+
const uploadFromUploaded = (uuid, { publicKey, fileName, baseURL, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, baseCDN }) => {
|
|
866
|
+
return info(uuid, {
|
|
867
|
+
publicKey,
|
|
868
|
+
baseURL,
|
|
869
|
+
signal,
|
|
870
|
+
source,
|
|
871
|
+
integration,
|
|
872
|
+
userAgent,
|
|
873
|
+
retryThrottledRequestMaxTimes,
|
|
874
|
+
retryNetworkErrorMaxTimes
|
|
875
|
+
})
|
|
876
|
+
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN, fileName }))
|
|
877
|
+
.then((result) => {
|
|
878
|
+
// hack for node ¯\_(ツ)_/¯
|
|
879
|
+
if (onProgress)
|
|
880
|
+
onProgress({
|
|
881
|
+
isComputable: true,
|
|
882
|
+
value: 1
|
|
883
|
+
});
|
|
884
|
+
return result;
|
|
885
|
+
});
|
|
886
|
+
};
|
|
887
|
+
|
|
838
888
|
const race = (fns, { signal } = {}) => {
|
|
839
889
|
let lastError = null;
|
|
840
890
|
let winnerIndex = null;
|
|
@@ -1174,35 +1224,30 @@ const uploadFromUrl = (sourceUrl, { publicKey, fileName, baseURL, baseCDN, check
|
|
|
1174
1224
|
}))
|
|
1175
1225
|
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN }));
|
|
1176
1226
|
|
|
1177
|
-
const
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
retryThrottledRequestMaxTimes,
|
|
1186
|
-
retryNetworkErrorMaxTimes
|
|
1187
|
-
})
|
|
1188
|
-
.then((fileInfo) => new UploadcareFile(fileInfo, { baseCDN, fileName }))
|
|
1189
|
-
.then((result) => {
|
|
1190
|
-
// hack for node ¯\_(ツ)_/¯
|
|
1191
|
-
if (onProgress)
|
|
1192
|
-
onProgress({
|
|
1193
|
-
isComputable: true,
|
|
1194
|
-
value: 1
|
|
1195
|
-
});
|
|
1196
|
-
return result;
|
|
1197
|
-
});
|
|
1227
|
+
const memo = new WeakMap();
|
|
1228
|
+
const getReactNativeBlob = async (asset) => {
|
|
1229
|
+
if (memo.has(asset)) {
|
|
1230
|
+
return memo.get(asset);
|
|
1231
|
+
}
|
|
1232
|
+
const blob = await fetch(asset.uri).then((res) => res.blob());
|
|
1233
|
+
memo.set(asset, blob);
|
|
1234
|
+
return blob;
|
|
1198
1235
|
};
|
|
1199
1236
|
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1237
|
+
const getFileSize = async (file) => {
|
|
1238
|
+
if (isBuffer(file)) {
|
|
1239
|
+
return file.length;
|
|
1240
|
+
}
|
|
1241
|
+
if (isFile(file) || isBlob(file)) {
|
|
1242
|
+
return file.size;
|
|
1243
|
+
}
|
|
1244
|
+
if (isReactNativeAsset(file)) {
|
|
1245
|
+
const blob = await getReactNativeBlob(file);
|
|
1246
|
+
return blob.size;
|
|
1247
|
+
}
|
|
1248
|
+
throw new Error(`Failed to get file size for file: ${file}`);
|
|
1205
1249
|
};
|
|
1250
|
+
|
|
1206
1251
|
/**
|
|
1207
1252
|
* Check if FileData is multipart data.
|
|
1208
1253
|
*/
|
|
@@ -1210,28 +1255,24 @@ const isMultipart = (fileSize, multipartMinFileSize = defaultSettings.multipartM
|
|
|
1210
1255
|
return fileSize >= multipartMinFileSize;
|
|
1211
1256
|
};
|
|
1212
1257
|
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1258
|
+
/**
|
|
1259
|
+
* Uuid type guard.
|
|
1260
|
+
*/
|
|
1261
|
+
const isUuid = (data) => {
|
|
1262
|
+
const UUID_REGEX = '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}';
|
|
1263
|
+
const regExp = new RegExp(UUID_REGEX);
|
|
1264
|
+
return !isFileData(data) && regExp.test(data);
|
|
1217
1265
|
};
|
|
1218
|
-
|
|
1219
1266
|
/**
|
|
1220
|
-
*
|
|
1221
|
-
*
|
|
1222
|
-
* We need to store references to sliced blobs to prevent source blob from
|
|
1223
|
-
* being deallocated until uploading complete. Access to deallocated blob
|
|
1224
|
-
* causes app crash.
|
|
1267
|
+
* Url type guard.
|
|
1225
1268
|
*
|
|
1226
|
-
*
|
|
1227
|
-
* and https://github.com/facebook/react-native/issues/27543
|
|
1269
|
+
* @param {AnyFile | Url | Uuid} data
|
|
1228
1270
|
*/
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
}
|
|
1271
|
+
const isUrl = (data) => {
|
|
1272
|
+
const URL_REGEX = '^(?:\\w+:)?\\/\\/([^\\s\\.]+\\.\\S{2}|localhost[\\:?\\d]*)\\S*$';
|
|
1273
|
+
const regExp = new RegExp(URL_REGEX);
|
|
1274
|
+
return !isFileData(data) && regExp.test(data);
|
|
1275
|
+
};
|
|
1235
1276
|
|
|
1236
1277
|
const runWithConcurrency = (concurrency, tasks) => {
|
|
1237
1278
|
return new Promise((resolve, reject) => {
|
|
@@ -1268,6 +1309,36 @@ const runWithConcurrency = (concurrency, tasks) => {
|
|
|
1268
1309
|
});
|
|
1269
1310
|
};
|
|
1270
1311
|
|
|
1312
|
+
const sliceChunk = (file, index, fileSize, chunkSize) => {
|
|
1313
|
+
const start = chunkSize * index;
|
|
1314
|
+
const end = Math.min(start + chunkSize, fileSize);
|
|
1315
|
+
return file.slice(start, end);
|
|
1316
|
+
};
|
|
1317
|
+
|
|
1318
|
+
/**
|
|
1319
|
+
* React-native hack for blob slicing
|
|
1320
|
+
*
|
|
1321
|
+
* We need to store references to sliced blobs to prevent source blob from
|
|
1322
|
+
* being deallocated until uploading complete. Access to deallocated blob
|
|
1323
|
+
* causes app crash.
|
|
1324
|
+
*
|
|
1325
|
+
* See https://github.com/uploadcare/uploadcare-js-api-clients/issues/306
|
|
1326
|
+
* and https://github.com/facebook/react-native/issues/27543
|
|
1327
|
+
*/
|
|
1328
|
+
const prepareChunks = async (file, fileSize, chunkSize) => {
|
|
1329
|
+
let blob;
|
|
1330
|
+
if (isReactNativeAsset(file)) {
|
|
1331
|
+
blob = await getReactNativeBlob(file);
|
|
1332
|
+
}
|
|
1333
|
+
else {
|
|
1334
|
+
blob = file;
|
|
1335
|
+
}
|
|
1336
|
+
return (index) => {
|
|
1337
|
+
const chunk = sliceChunk(blob, index, fileSize, chunkSize);
|
|
1338
|
+
return chunk;
|
|
1339
|
+
};
|
|
1340
|
+
};
|
|
1341
|
+
|
|
1271
1342
|
const uploadPart = (chunk, url, { publicKey, onProgress, signal, integration, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes }) => multipartUpload(chunk, url, {
|
|
1272
1343
|
publicKey,
|
|
1273
1344
|
onProgress,
|
|
@@ -1276,8 +1347,8 @@ const uploadPart = (chunk, url, { publicKey, onProgress, signal, integration, re
|
|
|
1276
1347
|
retryThrottledRequestMaxTimes,
|
|
1277
1348
|
retryNetworkErrorMaxTimes
|
|
1278
1349
|
});
|
|
1279
|
-
const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, contentType, multipartChunkSize = defaultSettings.multipartChunkSize, maxConcurrentRequests = defaultSettings.maxConcurrentRequests, baseCDN, metadata }) => {
|
|
1280
|
-
const size = fileSize || getFileSize(file);
|
|
1350
|
+
const uploadMultipart = async (file, { publicKey, fileName, fileSize, baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, contentType, multipartChunkSize = defaultSettings.multipartChunkSize, maxConcurrentRequests = defaultSettings.maxConcurrentRequests, baseCDN, metadata }) => {
|
|
1351
|
+
const size = fileSize || await getFileSize(file);
|
|
1281
1352
|
let progressValues;
|
|
1282
1353
|
const createProgressHandler = (totalChunks, chunkIdx) => {
|
|
1283
1354
|
if (!onProgress)
|
|
@@ -1299,8 +1370,8 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
|
|
|
1299
1370
|
};
|
|
1300
1371
|
return multipartStart(size, {
|
|
1301
1372
|
publicKey,
|
|
1302
|
-
contentType,
|
|
1303
|
-
fileName: fileName
|
|
1373
|
+
contentType: contentType || getContentType(file),
|
|
1374
|
+
fileName: fileName || getFilename(file),
|
|
1304
1375
|
baseURL,
|
|
1305
1376
|
secureSignature,
|
|
1306
1377
|
secureExpire,
|
|
@@ -1313,8 +1384,8 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
|
|
|
1313
1384
|
retryNetworkErrorMaxTimes,
|
|
1314
1385
|
metadata
|
|
1315
1386
|
})
|
|
1316
|
-
.then(({ uuid, parts }) => {
|
|
1317
|
-
const getChunk = prepareChunks(file, size, multipartChunkSize);
|
|
1387
|
+
.then(async ({ uuid, parts }) => {
|
|
1388
|
+
const getChunk = await prepareChunks(file, size, multipartChunkSize);
|
|
1318
1389
|
return Promise.all([
|
|
1319
1390
|
uuid,
|
|
1320
1391
|
runWithConcurrency(maxConcurrentRequests, parts.map((url, index) => () => uploadPart(getChunk(index), url, {
|
|
@@ -1361,14 +1432,15 @@ const uploadMultipart = (file, { publicKey, fileName, fileSize, baseURL, secureS
|
|
|
1361
1432
|
/**
|
|
1362
1433
|
* Uploads file from provided data.
|
|
1363
1434
|
*/
|
|
1364
|
-
function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, contentType, multipartMinFileSize, multipartChunkSize, maxConcurrentRequests, baseCDN = defaultSettings.baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, pusherKey, metadata }) {
|
|
1435
|
+
async function uploadFile(data, { publicKey, fileName, baseURL = defaultSettings.baseURL, secureSignature, secureExpire, store, signal, onProgress, source, integration, userAgent, retryThrottledRequestMaxTimes, retryNetworkErrorMaxTimes, contentType, multipartMinFileSize, multipartChunkSize, maxConcurrentRequests, baseCDN = defaultSettings.baseCDN, checkForUrlDuplicates, saveUrlForRecurrentUploads, pusherKey, metadata }) {
|
|
1365
1436
|
if (isFileData(data)) {
|
|
1366
|
-
const fileSize = getFileSize(data);
|
|
1437
|
+
const fileSize = await getFileSize(data);
|
|
1367
1438
|
if (isMultipart(fileSize, multipartMinFileSize)) {
|
|
1368
1439
|
return uploadMultipart(data, {
|
|
1369
1440
|
publicKey,
|
|
1370
1441
|
contentType,
|
|
1371
1442
|
multipartChunkSize,
|
|
1443
|
+
fileSize,
|
|
1372
1444
|
fileName,
|
|
1373
1445
|
baseURL,
|
|
1374
1446
|
secureSignature,
|