diff options
Diffstat (limited to 'activestorage/app/javascript/activestorage/file_checksum.js')
-rw-r--r-- | activestorage/app/javascript/activestorage/file_checksum.js | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/activestorage/app/javascript/activestorage/file_checksum.js b/activestorage/app/javascript/activestorage/file_checksum.js new file mode 100644 index 0000000000..ffaec1a128 --- /dev/null +++ b/activestorage/app/javascript/activestorage/file_checksum.js @@ -0,0 +1,53 @@ +import SparkMD5 from "spark-md5" + +const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice + +export class FileChecksum { + static create(file, callback) { + const instance = new FileChecksum(file) + instance.create(callback) + } + + 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 + } + } +} |