aboutsummaryrefslogtreecommitdiffstats
path: root/app/javascript/activestorage/file_checksum.js
diff options
context:
space:
mode:
Diffstat (limited to 'app/javascript/activestorage/file_checksum.js')
-rw-r--r--app/javascript/activestorage/file_checksum.js48
1 files changed, 48 insertions, 0 deletions
diff --git a/app/javascript/activestorage/file_checksum.js b/app/javascript/activestorage/file_checksum.js
new file mode 100644
index 0000000000..d7a10b3e55
--- /dev/null
+++ b/app/javascript/activestorage/file_checksum.js
@@ -0,0 +1,48 @@
+import SparkMD5 from "spark-md5"
+
+const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
+
+export class FileChecksum {
+ constructor(file) {
+ this.file = file
+ this.chunkSize = 2097152 // 2MB
+ this.chunkCount = Math.ceil(this.file.size / this.chunkSize)
+ this.chunkIndex = 0
+ }
+
+ create(callback) {
+ this.callback = callback
+ this.md5Buffer = new SparkMD5.ArrayBuffer
+ this.fileReader = new FileReader
+ this.fileReader.addEventListener("load", event => this.fileReaderDidLoad(event))
+ this.fileReader.addEventListener("error", event => this.fileReaderDidError(event))
+ this.readNextChunk()
+ }
+
+ fileReaderDidLoad(event) {
+ this.md5Buffer.append(event.target.result)
+
+ if (!this.readNextChunk()) {
+ const binaryDigest = this.md5Buffer.end(true)
+ const base64digest = btoa(binaryDigest)
+ this.callback(null, base64digest)
+ }
+ }
+
+ fileReaderDidError(event) {
+ this.callback(`Error reading ${this.file.name}`)
+ }
+
+ readNextChunk() {
+ if (this.chunkIndex < this.chunkCount) {
+ const start = this.chunkIndex * this.chunkSize
+ const end = Math.min(start + this.chunkSize, this.file.size)
+ const bytes = fileSlice.call(this.file, start, end)
+ this.fileReader.readAsArrayBuffer(bytes)
+ this.chunkIndex++
+ return true
+ } else {
+ return false
+ }
+ }
+}