Skip to content

Commit 91656ac

Browse files
committed
client-side checksum -not finished yet
partially copied from tus#347
1 parent 5923310 commit 91656ac

File tree

5 files changed

+23088
-5365
lines changed

5 files changed

+23088
-5365
lines changed

lib/browser/extensions/checksum.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
class Checksum {
2+
static supportedAlgorithms = ['SHA-1', 'SHA-256', 'SHA-384', 'SHA-512'];
3+
4+
constructor (algo = 'SHA-256') {
5+
this.algo = this._resolveAlgo(algo)
6+
}
7+
8+
/**
9+
* Resolves algorithm to one of the inbuilt types
10+
* @param {String} algo contains user provided checksumAlgo option
11+
*/
12+
_resolveAlgo = (algo) => {
13+
const resolvedAlgo = Checksum.supportedAlgorithms.find(supportedAlgo => supportedAlgo === algo.toUpperCase())
14+
if (!resolvedAlgo) {
15+
throw new Error(
16+
`tus: unsupported checksumAlgo provided. Supported values are : ${Checksum.supportedAlgorithms.join(',')}`,
17+
)
18+
}
19+
return resolvedAlgo
20+
}
21+
22+
/**
23+
* Gets hexadecimal digest using the algorithm set in this.algo
24+
* @param {ArrayBuffer} data contains the chunk of data to be hashed
25+
*/
26+
getHexDigest = async (data) => {
27+
try {
28+
const hashBuffer = await crypto.subtle.digest(this.algo, data)
29+
const hashArray = Array.from(new Uint8Array(hashBuffer)) // convert buffer to byte array
30+
const hashHex = hashArray
31+
.map((b) => b.toString(16).padStart(2, '0'))
32+
.join('') // convert bytes to hex string
33+
return hashHex
34+
} catch (err) {
35+
throw new Error('tus: could not compute checksum for integrity check')
36+
}
37+
};
38+
}
39+
40+
export default Checksum

lib/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ interface UploadOptions {
4242

4343
chunkSize?: number;
4444
retryDelays?: number[];
45+
enableChecksum?: boolean | null;
4546
parallelUploads?: number;
4647
parallelUploadBoundaries?: { start: number; end: number }[] | null;
4748
storeFingerprintForResuming?: boolean; removeFingerprintOnSuccess?: boolean;

lib/upload.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import URL from 'url-parse'
33
import DetailedError from './error.js'
44
import { log } from './logger.js'
55
import uuid from './uuid.js'
6+
import Checksum from './browser/extensions/checksum.js'
67

78
const defaultOptions = {
89
endpoint: null,
@@ -100,6 +101,9 @@ class BaseUpload {
100101
// An array of upload URLs which are used for uploading the different
101102
// parts, if the parallelUploads option is used.
102103
this._parallelUploadUrls = null
104+
105+
// A platform dependent checksum generator, this is instantiated if options.enableChecksum is provided
106+
this._checksum = null
103107
}
104108

105109
/**
@@ -531,6 +535,11 @@ class BaseUpload {
531535
return
532536
}
533537

538+
// eslint-disable-next-line no-undef
539+
if (this.options.enableChecksum && window) {
540+
this._checksum = new Checksum()
541+
}
542+
534543
const req = this._openRequest('POST', this.options.endpoint)
535544

536545
if (this.options.uploadLengthDeferred) {
@@ -749,6 +758,17 @@ class BaseUpload {
749758
req.setHeader('Upload-Length', this._size)
750759
}
751760

761+
if (this.options.enableChecksum && this._checksum) {
762+
value.arrayBuffer().then((chunkBuffer) => {
763+
this._checksum
764+
.getHexDigest(chunkBuffer)
765+
.then((hash) => {
766+
console.log('Upload-Checksum', `${this._checksum.algo} ${hash}`)
767+
})
768+
.catch((err) => log(err))
769+
})
770+
}
771+
752772
if (value === null) {
753773
return this._sendRequest(req)
754774
}

0 commit comments

Comments
 (0)