activestorage/app/javascript/activestorage/file_checksum.js
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 || (this.chunkIndex == 0 && this.chunkCount == 0)) {
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
}
}
}