@eluvio/elv-client-js 4.0.20 → 4.0.22
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/ElvClient-min.js +4 -4
- package/dist/ElvClient-node-min.js +4 -4
- package/dist/ElvFrameClient-min.js +1 -1
- package/dist/ElvWalletClient-min.js +4 -4
- package/dist/ElvWalletClient-node-min.js +8 -8
- package/dist/src/AuthorizationClient.js +1 -0
- package/dist/src/HttpClient.js +37 -21
- package/dist/src/client/ContentAccess.js +2 -1
- package/dist/src/client/ContentManagement.js +4 -4
- package/dist/src/client/Files.js +480 -475
- package/package.json +1 -1
- package/src/AuthorizationClient.js +1 -1
- package/src/HttpClient.js +21 -6
- package/src/client/ContentAccess.js +2 -2
- package/src/client/ContentManagement.js +4 -4
- package/src/client/Files.js +81 -81
- package/testScripts/Test.js +1 -2
- package/testScripts/UploadFilesTest.js +84 -0
- package/testScripts/abr_profile_4k_both.json +0 -10
- package/testScripts/abr_profile_4k_drm_public_access.json +128 -0
- package/testScripts/abr_profile_both.json +0 -10
- package/testScripts/abr_profile_drm_public_access.json +1962 -0
- package/utilities/example_files/abr_profile_4k_both.json +0 -10
- package/utilities/example_files/abr_profile_4k_drm_public_access.json +128 -0
- package/utilities/example_files/abr_profile_both.json +0 -10
- package/utilities/example_files/abr_profile_drm_public_access.json +1916 -0
package/package.json
CHANGED
|
@@ -192,7 +192,7 @@ class AuthorizationClient {
|
|
|
192
192
|
if(encryption && encryption !== "none" && objectId && await this.AccessType(objectId) === ACCESS_TYPES.OBJECT) {
|
|
193
193
|
const owner = await this.Owner({id: objectId});
|
|
194
194
|
const ownerCapKey = `eluv.caps.iusr${Utils.AddressToHash(this.client.signer.address)}`;
|
|
195
|
-
const ownerCap = await this.client.ContentObjectMetadata({libraryId, objectId, metadataSubtree: ownerCapKey});
|
|
195
|
+
const ownerCap = await this.client.ContentObjectMetadata({libraryId, objectId, versionHash, metadataSubtree: ownerCapKey});
|
|
196
196
|
|
|
197
197
|
if(!Utils.EqualAddress(owner, this.client.signer.address) && !ownerCap) {
|
|
198
198
|
const cap = await this.ReEncryptionConk({libraryId, objectId});
|
package/src/HttpClient.js
CHANGED
|
@@ -12,6 +12,7 @@ class HttpClient {
|
|
|
12
12
|
this.uriIndex = 0;
|
|
13
13
|
this.debug = debug;
|
|
14
14
|
this.draftURIs = {};
|
|
15
|
+
this.retries = Math.max(3, uris.length);
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
BaseURI() {
|
|
@@ -50,8 +51,9 @@ class HttpClient {
|
|
|
50
51
|
bodyType="JSON",
|
|
51
52
|
headers={},
|
|
52
53
|
attempts=0,
|
|
53
|
-
|
|
54
|
-
forceFailover=false
|
|
54
|
+
allowFailover=true,
|
|
55
|
+
forceFailover=false,
|
|
56
|
+
allowRetry=true
|
|
55
57
|
}) {
|
|
56
58
|
let baseURI = this.BaseURI();
|
|
57
59
|
|
|
@@ -60,6 +62,8 @@ class HttpClient {
|
|
|
60
62
|
const writeToken = writeTokenMatch ? writeTokenMatch[2] : undefined;
|
|
61
63
|
|
|
62
64
|
if(writeToken) {
|
|
65
|
+
allowFailover = false;
|
|
66
|
+
|
|
63
67
|
if(this.draftURIs[writeToken]) {
|
|
64
68
|
// Use saved write token URI
|
|
65
69
|
baseURI = this.draftURIs[writeToken];
|
|
@@ -107,10 +111,21 @@ class HttpClient {
|
|
|
107
111
|
|
|
108
112
|
if(!response.ok) {
|
|
109
113
|
// Fail over if not a write token request, the response was a server error, and we haven't tried all available nodes
|
|
110
|
-
if(
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
+
if(
|
|
115
|
+
(parseInt(response.status) >= 500 || forceFailover) &&
|
|
116
|
+
allowRetry &&
|
|
117
|
+
attempts < this.retries
|
|
118
|
+
) {
|
|
119
|
+
// Server error
|
|
120
|
+
if(allowFailover) {
|
|
121
|
+
// Fail over to alternate node
|
|
122
|
+
this.uriIndex = (this.uriIndex + 1) % this.uris.length;
|
|
123
|
+
this.Log(`HttpClient failing over from ${baseURI.toString()}: ${attempts + 1} attempts`, true);
|
|
124
|
+
} else {
|
|
125
|
+
// Wait and retry
|
|
126
|
+
this.Log(`HttpClient retrying request from ${baseURI.toString()}: ${attempts + 1} attempts`, true);
|
|
127
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
128
|
+
}
|
|
114
129
|
|
|
115
130
|
return await this.Request({
|
|
116
131
|
method,
|
|
@@ -1831,7 +1831,7 @@ exports.CallBitcodeMethod = async function({
|
|
|
1831
1831
|
method: constant ? "GET" : "POST",
|
|
1832
1832
|
path,
|
|
1833
1833
|
queryParams,
|
|
1834
|
-
|
|
1834
|
+
allowFailover: false
|
|
1835
1835
|
})
|
|
1836
1836
|
);
|
|
1837
1837
|
};
|
|
@@ -2477,7 +2477,7 @@ exports.EncryptionConk = async function({libraryId, objectId, versionHash, write
|
|
|
2477
2477
|
const owner = await this.authClient.Owner({id: objectId});
|
|
2478
2478
|
|
|
2479
2479
|
const ownerCapKey = `eluv.caps.iusr${this.utils.AddressToHash(this.signer.address)}`;
|
|
2480
|
-
const ownerCap = await this.ContentObjectMetadata({libraryId, objectId, metadataSubtree: ownerCapKey});
|
|
2480
|
+
const ownerCap = await this.ContentObjectMetadata({libraryId, objectId, versionHash, metadataSubtree: ownerCapKey});
|
|
2481
2481
|
|
|
2482
2482
|
if(!this.utils.EqualAddress(owner, this.signer.address) && !ownerCap) {
|
|
2483
2483
|
if(download) {
|
|
@@ -967,7 +967,7 @@ exports.FinalizeContentObject = async function({
|
|
|
967
967
|
headers: await this.authClient.AuthorizationHeader({libraryId, objectId, update: true}),
|
|
968
968
|
method: "POST",
|
|
969
969
|
path: path,
|
|
970
|
-
|
|
970
|
+
allowFailover: false
|
|
971
971
|
})
|
|
972
972
|
);
|
|
973
973
|
|
|
@@ -1127,7 +1127,7 @@ exports.MergeMetadata = async function({libraryId, objectId, writeToken, metadat
|
|
|
1127
1127
|
method: "POST",
|
|
1128
1128
|
path: path,
|
|
1129
1129
|
body: metadata,
|
|
1130
|
-
|
|
1130
|
+
allowFailover: false
|
|
1131
1131
|
});
|
|
1132
1132
|
};
|
|
1133
1133
|
|
|
@@ -1159,7 +1159,7 @@ exports.ReplaceMetadata = async function({libraryId, objectId, writeToken, metad
|
|
|
1159
1159
|
method: "PUT",
|
|
1160
1160
|
path: path,
|
|
1161
1161
|
body: metadata,
|
|
1162
|
-
|
|
1162
|
+
allowFailover: false
|
|
1163
1163
|
});
|
|
1164
1164
|
};
|
|
1165
1165
|
|
|
@@ -1190,7 +1190,7 @@ exports.DeleteMetadata = async function({libraryId, objectId, writeToken, metada
|
|
|
1190
1190
|
headers: await this.authClient.AuthorizationHeader({libraryId, objectId, update: true}),
|
|
1191
1191
|
method: "DELETE",
|
|
1192
1192
|
path: path,
|
|
1193
|
-
|
|
1193
|
+
allowFailover: false
|
|
1194
1194
|
});
|
|
1195
1195
|
};
|
|
1196
1196
|
|
package/src/client/Files.js
CHANGED
|
@@ -267,6 +267,7 @@ exports.UploadFilesFromS3 = async function({
|
|
|
267
267
|
exports.UploadFiles = async function({libraryId, objectId, writeToken, fileInfo, encryption="none", callback}) {
|
|
268
268
|
ValidateParameters({libraryId, objectId});
|
|
269
269
|
ValidateWriteToken(writeToken);
|
|
270
|
+
ValidatePresence("fileInfo", fileInfo);
|
|
270
271
|
|
|
271
272
|
this.Log(`Uploading files: ${libraryId} ${objectId} ${writeToken}`);
|
|
272
273
|
|
|
@@ -279,8 +280,10 @@ exports.UploadFiles = async function({libraryId, objectId, writeToken, fileInfo,
|
|
|
279
280
|
let progress = {};
|
|
280
281
|
let fileDataMap = {};
|
|
281
282
|
|
|
282
|
-
|
|
283
|
-
|
|
283
|
+
let originalFileInfo = fileInfo;
|
|
284
|
+
fileInfo = [];
|
|
285
|
+
for(let i = 0; i < originalFileInfo.length; i++) {
|
|
286
|
+
let entry = { ...originalFileInfo[i], data: undefined };
|
|
284
287
|
|
|
285
288
|
entry.path = entry.path.replace(/^\/+/, "");
|
|
286
289
|
|
|
@@ -290,9 +293,8 @@ exports.UploadFiles = async function({libraryId, objectId, writeToken, fileInfo,
|
|
|
290
293
|
};
|
|
291
294
|
}
|
|
292
295
|
|
|
293
|
-
fileDataMap[entry.path] =
|
|
296
|
+
fileDataMap[entry.path] = originalFileInfo[i].data;
|
|
294
297
|
|
|
295
|
-
delete entry.data;
|
|
296
298
|
entry.type = "file";
|
|
297
299
|
|
|
298
300
|
progress[entry.path] = {
|
|
@@ -300,7 +302,7 @@ exports.UploadFiles = async function({libraryId, objectId, writeToken, fileInfo,
|
|
|
300
302
|
total: entry.size
|
|
301
303
|
};
|
|
302
304
|
|
|
303
|
-
fileInfo
|
|
305
|
+
fileInfo.push(entry);
|
|
304
306
|
}
|
|
305
307
|
|
|
306
308
|
this.Log(fileInfo);
|
|
@@ -321,7 +323,7 @@ exports.UploadFiles = async function({libraryId, objectId, writeToken, fileInfo,
|
|
|
321
323
|
this.Log(jobs);
|
|
322
324
|
|
|
323
325
|
// How far encryption can get ahead of upload
|
|
324
|
-
const bufferSize =
|
|
326
|
+
const bufferSize = 500 * 1024 * 1024;
|
|
325
327
|
|
|
326
328
|
let jobSpecs = [];
|
|
327
329
|
let prepared = 0;
|
|
@@ -387,7 +389,34 @@ exports.UploadFiles = async function({libraryId, objectId, writeToken, fileInfo,
|
|
|
387
389
|
for(let f = 0; f < files.length; f++) {
|
|
388
390
|
const fileInfo = files[f];
|
|
389
391
|
|
|
390
|
-
|
|
392
|
+
let retries = 0;
|
|
393
|
+
let succeeded = false;
|
|
394
|
+
do {
|
|
395
|
+
try {
|
|
396
|
+
await this.UploadFileData({
|
|
397
|
+
libraryId,
|
|
398
|
+
objectId,
|
|
399
|
+
writeToken,
|
|
400
|
+
uploadId: id,
|
|
401
|
+
jobId,
|
|
402
|
+
filePath: fileInfo.path,
|
|
403
|
+
fileData: fileInfo.data,
|
|
404
|
+
encryption
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
succeeded = true;
|
|
408
|
+
} catch(error) {
|
|
409
|
+
this.Log(error, true);
|
|
410
|
+
|
|
411
|
+
retries += 1;
|
|
412
|
+
|
|
413
|
+
if(retries >= 10) {
|
|
414
|
+
throw error;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
await new Promise(resolve => setTimeout(resolve, 10 * retries * 1000));
|
|
418
|
+
}
|
|
419
|
+
} while(!succeeded && retries < 10);
|
|
391
420
|
|
|
392
421
|
delete jobSpecs[j].files[f].data;
|
|
393
422
|
uploaded += fileInfo.len;
|
|
@@ -460,7 +489,7 @@ exports.CreateFileUploadJob = async function({libraryId, objectId, writeToken, o
|
|
|
460
489
|
method: "POST",
|
|
461
490
|
path: path,
|
|
462
491
|
body,
|
|
463
|
-
|
|
492
|
+
allowFailover: false
|
|
464
493
|
})
|
|
465
494
|
);
|
|
466
495
|
};
|
|
@@ -476,7 +505,7 @@ exports.UploadStatus = async function({libraryId, objectId, writeToken, uploadId
|
|
|
476
505
|
headers: await this.authClient.AuthorizationHeader({libraryId, objectId, update: true}),
|
|
477
506
|
method: "GET",
|
|
478
507
|
path: path,
|
|
479
|
-
|
|
508
|
+
allowFailover: false
|
|
480
509
|
})
|
|
481
510
|
);
|
|
482
511
|
};
|
|
@@ -487,80 +516,51 @@ exports.UploadJobStatus = async function({libraryId, objectId, writeToken, uploa
|
|
|
487
516
|
|
|
488
517
|
const path = UrlJoin("q", writeToken, "file_jobs", uploadId, "uploads", jobId);
|
|
489
518
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
failover: false
|
|
499
|
-
})
|
|
500
|
-
);
|
|
501
|
-
return jobStatus;
|
|
502
|
-
} catch(error) {
|
|
503
|
-
this.Log(error, true);
|
|
504
|
-
|
|
505
|
-
retries += 1;
|
|
506
|
-
if(retries >= 5) {
|
|
507
|
-
throw error;
|
|
508
|
-
}
|
|
509
|
-
await new Promise(resolve => setTimeout(resolve, 10 * retries * 1000));
|
|
510
|
-
}
|
|
511
|
-
} while(retries < 5);
|
|
512
|
-
|
|
519
|
+
return await this.utils.ResponseToJson(
|
|
520
|
+
this.HttpClient.Request({
|
|
521
|
+
headers: await this.authClient.AuthorizationHeader({libraryId, objectId, update: true}),
|
|
522
|
+
method: "GET",
|
|
523
|
+
path: path,
|
|
524
|
+
allowFailover: false
|
|
525
|
+
})
|
|
526
|
+
);
|
|
513
527
|
};
|
|
514
528
|
|
|
515
|
-
exports.UploadFileData = async function({libraryId, objectId, writeToken, uploadId, jobId, filePath, fileData}) {
|
|
529
|
+
exports.UploadFileData = async function({libraryId, objectId, writeToken, encryption, uploadId, jobId, filePath, fileData}) {
|
|
516
530
|
ValidateParameters({libraryId, objectId});
|
|
517
531
|
ValidateWriteToken(writeToken);
|
|
518
532
|
|
|
519
|
-
|
|
520
|
-
do {
|
|
521
|
-
try {
|
|
522
|
-
|
|
523
|
-
const jobStatus = await this.UploadJobStatus({libraryId, objectId, writeToken, uploadId, jobId});
|
|
524
|
-
|
|
525
|
-
// Find the status of this file
|
|
526
|
-
const fileStatus = jobStatus.files.find(item => {
|
|
527
|
-
return item.path == filePath
|
|
528
|
-
});
|
|
529
|
-
|
|
530
|
-
if(fileStatus.rem === 0) {
|
|
531
|
-
// Job is actually done
|
|
532
|
-
return;
|
|
533
|
-
} else if(fileStatus.skip) {
|
|
534
|
-
fileData = fileData.slice(fileStatus.skip);
|
|
535
|
-
}
|
|
533
|
+
const jobStatus = await this.UploadJobStatus({libraryId, objectId, writeToken, uploadId, jobId});
|
|
536
534
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
path: path,
|
|
543
|
-
body: fileData,
|
|
544
|
-
bodyType: "BINARY",
|
|
545
|
-
headers: {
|
|
546
|
-
"Content-type": "application/octet-stream",
|
|
547
|
-
...(await this.authClient.AuthorizationHeader({libraryId, objectId, update: true}))
|
|
548
|
-
},
|
|
549
|
-
failover: false
|
|
550
|
-
})
|
|
551
|
-
);
|
|
552
|
-
} catch(error){
|
|
553
|
-
this.Log(error, true);
|
|
535
|
+
// Find the status of this file
|
|
536
|
+
let fileStatus = jobStatus.files.find(item => item.path == filePath);
|
|
537
|
+
if(encryption && encryption !== "none") {
|
|
538
|
+
fileStatus = fileStatus.encrypted;
|
|
539
|
+
}
|
|
554
540
|
|
|
555
|
-
|
|
541
|
+
if(fileStatus.rem === 0) {
|
|
542
|
+
// Job is actually done
|
|
543
|
+
return;
|
|
544
|
+
} else if(fileStatus.skip) {
|
|
545
|
+
fileData = fileData.slice(fileStatus.skip);
|
|
546
|
+
}
|
|
556
547
|
|
|
557
|
-
|
|
558
|
-
throw error;
|
|
559
|
-
}
|
|
548
|
+
let path = UrlJoin("q", writeToken, "file_jobs", uploadId, jobId);
|
|
560
549
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
550
|
+
return await this.utils.ResponseToJson(
|
|
551
|
+
this.HttpClient.Request({
|
|
552
|
+
method: "POST",
|
|
553
|
+
path: path,
|
|
554
|
+
body: fileData,
|
|
555
|
+
bodyType: "BINARY",
|
|
556
|
+
headers: {
|
|
557
|
+
"Content-type": "application/octet-stream",
|
|
558
|
+
...(await this.authClient.AuthorizationHeader({libraryId, objectId, update: true}))
|
|
559
|
+
},
|
|
560
|
+
allowFailover: false,
|
|
561
|
+
allowRetry: false
|
|
562
|
+
})
|
|
563
|
+
);
|
|
564
564
|
};
|
|
565
565
|
|
|
566
566
|
exports.FinalizeUploadJob = async function({libraryId, objectId, writeToken}) {
|
|
@@ -576,7 +576,7 @@ exports.FinalizeUploadJob = async function({libraryId, objectId, writeToken}) {
|
|
|
576
576
|
path: path,
|
|
577
577
|
bodyType: "BINARY",
|
|
578
578
|
headers: await this.authClient.AuthorizationHeader({libraryId, objectId, update: true}),
|
|
579
|
-
|
|
579
|
+
allowFailover: false
|
|
580
580
|
});
|
|
581
581
|
};
|
|
582
582
|
|
|
@@ -637,7 +637,7 @@ exports.DeleteFiles = async function({libraryId, objectId, writeToken, filePaths
|
|
|
637
637
|
* @param {string=} versionHash - Hash of the object version - if not specified, latest version will be used
|
|
638
638
|
* @param {string=} writeToken - Write token for the draft from which to download the file
|
|
639
639
|
* @param {string} filePath - Path to the file to download
|
|
640
|
-
* @param {string=} format="
|
|
640
|
+
* @param {string=} format="arrayBuffer" - Format in which to return the data ("blob" | "arraybuffer" | "buffer")
|
|
641
641
|
* @param {boolean=} chunked=false - If specified, file will be downloaded and decrypted in chunks. The
|
|
642
642
|
* specified callback will be invoked on completion of each chunk. This is recommended for large files.
|
|
643
643
|
* @param {number=} chunkSize=1000000 - Size of file chunks to request for download
|
|
@@ -689,7 +689,7 @@ exports.DownloadFile = async function({
|
|
|
689
689
|
|
|
690
690
|
// If not owner, indicate re-encryption
|
|
691
691
|
const ownerCapKey = `eluv.caps.iusr${this.utils.AddressToHash(this.signer.address)}`;
|
|
692
|
-
const ownerCap = await this.ContentObjectMetadata({libraryId, objectId, metadataSubtree: ownerCapKey});
|
|
692
|
+
const ownerCap = await this.ContentObjectMetadata({libraryId, objectId, versionHash, metadataSubtree: ownerCapKey});
|
|
693
693
|
|
|
694
694
|
if(encrypted && !this.utils.EqualAddress(this.signer.address, await this.ContentObjectOwner({objectId})) && !ownerCap) {
|
|
695
695
|
headers["X-Content-Fabric-Decryption-Mode"] = "reencrypt";
|
|
@@ -1040,7 +1040,7 @@ exports.CreatePart = async function({libraryId, objectId, writeToken, encryption
|
|
|
1040
1040
|
path,
|
|
1041
1041
|
bodyType: "BINARY",
|
|
1042
1042
|
body: "",
|
|
1043
|
-
|
|
1043
|
+
allowFailover: false
|
|
1044
1044
|
})
|
|
1045
1045
|
);
|
|
1046
1046
|
|
|
@@ -1079,7 +1079,7 @@ exports.UploadPartChunk = async function({libraryId, objectId, writeToken, partW
|
|
|
1079
1079
|
path: UrlJoin(path, partWriteToken),
|
|
1080
1080
|
body: chunk,
|
|
1081
1081
|
bodyType: "BINARY",
|
|
1082
|
-
|
|
1082
|
+
allowFailover: false
|
|
1083
1083
|
})
|
|
1084
1084
|
);
|
|
1085
1085
|
};
|
|
@@ -1110,7 +1110,7 @@ exports.FinalizePart = async function({libraryId, objectId, writeToken, partWrit
|
|
|
1110
1110
|
path: UrlJoin(path, partWriteToken),
|
|
1111
1111
|
bodyType: "BINARY",
|
|
1112
1112
|
body: "",
|
|
1113
|
-
|
|
1113
|
+
allowFailover: false
|
|
1114
1114
|
})
|
|
1115
1115
|
);
|
|
1116
1116
|
};
|
|
@@ -1189,6 +1189,6 @@ exports.DeletePart = async function({libraryId, objectId, writeToken, partHash})
|
|
|
1189
1189
|
headers: await this.authClient.AuthorizationHeader({libraryId, objectId, update: true}),
|
|
1190
1190
|
method: "DELETE",
|
|
1191
1191
|
path: path,
|
|
1192
|
-
|
|
1192
|
+
allowFailover: false
|
|
1193
1193
|
});
|
|
1194
1194
|
};
|
package/testScripts/Test.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
const { ElvClient } = require("../src/ElvClient");
|
|
2
2
|
const { ElvWalletClient } = require("../src/walletClient/index");
|
|
3
3
|
const ClientConfiguration = require("../TestConfiguration.json");
|
|
4
|
-
|
|
5
|
-
const ethers = require("ethers");
|
|
4
|
+
const fs = require("fs");
|
|
6
5
|
|
|
7
6
|
const Test = async () => {
|
|
8
7
|
try {
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
const { ElvClient } = require("../src/ElvClient");
|
|
2
|
+
const { ElvWalletClient } = require("../src/walletClient/index");
|
|
3
|
+
const ClientConfiguration = require("../TestConfiguration.json");
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
|
|
7
|
+
const createHash = require("node:crypto").createHash;
|
|
8
|
+
const MD5 = str => {
|
|
9
|
+
const f = createHash("md5");
|
|
10
|
+
f.update(str);
|
|
11
|
+
return f.digest("hex");
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const Test = async () => {
|
|
15
|
+
try {
|
|
16
|
+
const client = await ElvClient.FromNetworkName({
|
|
17
|
+
networkName: "demo"
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const wallet = client.GenerateWallet();
|
|
21
|
+
const signer = wallet.AddAccount({
|
|
22
|
+
privateKey: process.env.PRIVATE_KEY
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
client.SetSigner({signer});
|
|
26
|
+
|
|
27
|
+
const uploadDir = process.argv[2];
|
|
28
|
+
|
|
29
|
+
const dirname = `upload-test-${Date.now()}`;
|
|
30
|
+
const fileList = fs.readdirSync(uploadDir);
|
|
31
|
+
const fileInfo = fileList.map(filename => {
|
|
32
|
+
const data = fs.readFileSync(path.join(uploadDir, filename));
|
|
33
|
+
|
|
34
|
+
return {
|
|
35
|
+
path: `${dirname}/${filename}`,
|
|
36
|
+
size: data.length,
|
|
37
|
+
data
|
|
38
|
+
};
|
|
39
|
+
}).sort(() => Math.random() > 0.5 ? -1 : 1);
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
const libraryId = "ilib3Drbefo7VPfWvY1NVup4VZFzDJ68";
|
|
43
|
+
const objectId = "iq__2aqbcJhSKdkuRmAUqs6v99SLRRp";
|
|
44
|
+
|
|
45
|
+
const {hash} = await client.EditAndFinalizeContentObject({
|
|
46
|
+
libraryId,
|
|
47
|
+
objectId,
|
|
48
|
+
callback: async ({writeToken}) => {
|
|
49
|
+
await client.UploadFiles({
|
|
50
|
+
libraryId,
|
|
51
|
+
objectId,
|
|
52
|
+
writeToken,
|
|
53
|
+
//callback: console.log,
|
|
54
|
+
//encryption: "cgck",
|
|
55
|
+
fileInfo
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
console.log("\n\n");
|
|
61
|
+
for(let i = 0; i < fileInfo.length; i++) {
|
|
62
|
+
const {path, data} = fileInfo[i];
|
|
63
|
+
|
|
64
|
+
const downloadedData = await client.DownloadFile({
|
|
65
|
+
versionHash: hash,
|
|
66
|
+
format: "buffer",
|
|
67
|
+
filePath: path
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
console.log(path);
|
|
71
|
+
console.log(MD5(data.toString()));
|
|
72
|
+
console.log(MD5(downloadedData.toString()));
|
|
73
|
+
console.log(MD5(data.toString()) === MD5(downloadedData.toString()));
|
|
74
|
+
console.log();
|
|
75
|
+
}
|
|
76
|
+
} catch(error) {
|
|
77
|
+
console.error(error);
|
|
78
|
+
console.error(JSON.stringify(error, null, 2));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
process.exit(0);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
Test();
|
|
@@ -105,16 +105,6 @@
|
|
|
105
105
|
"type": "ProtoHls"
|
|
106
106
|
}
|
|
107
107
|
},
|
|
108
|
-
"hls-fairplay": {
|
|
109
|
-
"drm": {
|
|
110
|
-
"enc_scheme_name": "cbcs",
|
|
111
|
-
"license_servers": [],
|
|
112
|
-
"type": "DrmFairplay"
|
|
113
|
-
},
|
|
114
|
-
"protocol": {
|
|
115
|
-
"type": "ProtoHls"
|
|
116
|
-
}
|
|
117
|
-
},
|
|
118
108
|
"hls-sample-aes": {
|
|
119
109
|
"drm": {
|
|
120
110
|
"enc_scheme_name": "cbcs",
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
{
|
|
2
|
+
"drm_optional": false,
|
|
3
|
+
"store_clear": false,
|
|
4
|
+
"ladder_specs": {
|
|
5
|
+
"{\"media_type\":\"audio\",\"channels\":1}": {
|
|
6
|
+
"rung_specs": [
|
|
7
|
+
{
|
|
8
|
+
"bit_rate": 128000,
|
|
9
|
+
"media_type": "audio",
|
|
10
|
+
"pregenerate": true
|
|
11
|
+
}
|
|
12
|
+
]
|
|
13
|
+
},
|
|
14
|
+
"{\"media_type\":\"audio\",\"channels\":2}": {
|
|
15
|
+
"rung_specs": [
|
|
16
|
+
{
|
|
17
|
+
"bit_rate": 192000,
|
|
18
|
+
"media_type": "audio",
|
|
19
|
+
"pregenerate": true
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"{\"media_type\":\"audio\",\"channels\":6}": {
|
|
24
|
+
"rung_specs": [
|
|
25
|
+
{
|
|
26
|
+
"bit_rate": 384000,
|
|
27
|
+
"media_type": "audio",
|
|
28
|
+
"pregenerate": true
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"{\"media_type\":\"video\",\"aspect_ratio_height\":9,\"aspect_ratio_width\":16}": {
|
|
33
|
+
"rung_specs": [
|
|
34
|
+
{
|
|
35
|
+
"bit_rate": 20000000,
|
|
36
|
+
"height": 2160,
|
|
37
|
+
"media_type": "video",
|
|
38
|
+
"pregenerate": true,
|
|
39
|
+
"width": 3840
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"bit_rate": 9500000,
|
|
43
|
+
"height": 1080,
|
|
44
|
+
"media_type": "video",
|
|
45
|
+
"pregenerate": false,
|
|
46
|
+
"width": 1920
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"bit_rate": 4500000,
|
|
50
|
+
"height":720 ,
|
|
51
|
+
"media_type": "video",
|
|
52
|
+
"pregenerate": false,
|
|
53
|
+
"width": 1280
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"bit_rate": 2000000,
|
|
57
|
+
"height": 540,
|
|
58
|
+
"media_type": "video",
|
|
59
|
+
"pregenerate": false,
|
|
60
|
+
"width": 960
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"bit_rate": 1100000,
|
|
64
|
+
"height": 432,
|
|
65
|
+
"media_type": "video",
|
|
66
|
+
"pregenerate": false,
|
|
67
|
+
"width": 768
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"bit_rate": 810000,
|
|
71
|
+
"height": 360,
|
|
72
|
+
"media_type": "video",
|
|
73
|
+
"pregenerate": false,
|
|
74
|
+
"width": 640
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"bit_rate": 520000,
|
|
78
|
+
"height": 360,
|
|
79
|
+
"media_type": "video",
|
|
80
|
+
"pregenerate": false,
|
|
81
|
+
"width": 640
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"playout_formats": {
|
|
87
|
+
"dash-widevine": {
|
|
88
|
+
"drm": {
|
|
89
|
+
"content_id": "",
|
|
90
|
+
"enc_scheme_name": "cenc",
|
|
91
|
+
"license_servers": [],
|
|
92
|
+
"type": "DrmWidevine"
|
|
93
|
+
},
|
|
94
|
+
"protocol": {
|
|
95
|
+
"min_buffer_length": 2,
|
|
96
|
+
"type": "ProtoDash"
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"hls-sample-aes": {
|
|
100
|
+
"drm": {
|
|
101
|
+
"enc_scheme_name": "cbcs",
|
|
102
|
+
"type": "DrmSampleAes"
|
|
103
|
+
},
|
|
104
|
+
"protocol": {
|
|
105
|
+
"type": "ProtoHls"
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
"hls-aes128": {
|
|
109
|
+
"drm": {
|
|
110
|
+
"enc_scheme_name": "aes-128",
|
|
111
|
+
"type": "DrmAes128"
|
|
112
|
+
},
|
|
113
|
+
"protocol": {
|
|
114
|
+
"type": "ProtoHls"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"segment_specs": {
|
|
119
|
+
"audio": {
|
|
120
|
+
"segs_per_chunk": 15,
|
|
121
|
+
"target_dur": 2
|
|
122
|
+
},
|
|
123
|
+
"video": {
|
|
124
|
+
"segs_per_chunk": 15,
|
|
125
|
+
"target_dur": 2
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -1930,16 +1930,6 @@
|
|
|
1930
1930
|
"type": "ProtoDash"
|
|
1931
1931
|
}
|
|
1932
1932
|
},
|
|
1933
|
-
"hls-fairplay": {
|
|
1934
|
-
"drm": {
|
|
1935
|
-
"enc_scheme_name": "cbcs",
|
|
1936
|
-
"license_servers": [],
|
|
1937
|
-
"type": "DrmFairplay"
|
|
1938
|
-
},
|
|
1939
|
-
"protocol": {
|
|
1940
|
-
"type": "ProtoHls"
|
|
1941
|
-
}
|
|
1942
|
-
},
|
|
1943
1933
|
"hls-sample-aes": {
|
|
1944
1934
|
"drm": {
|
|
1945
1935
|
"enc_scheme_name": "cbcs",
|