Skip to content

Instantly share code, notes, and snippets.

@ghostzero
Created February 24, 2025 18:59
Show Gist options
  • Select an option

  • Save ghostzero/69ad760021f0bbe7d7cb0d81c74c6de2 to your computer and use it in GitHub Desktop.

Select an option

Save ghostzero/69ad760021f0bbe7d7cb0d81c74c6de2 to your computer and use it in GitHub Desktop.
import crypto from 'crypto'
import fs from 'fs'
const chunkSize = 16777216;
console.log(await calculateForFile('video.mp4', chunkSize));
function calculateForFile(filename, chunkSize) {
return new Promise((resolve, reject) => {
const stream = fs.createReadStream(filename, { highWaterMark: chunkSize });
calculate(stream, chunkSize)
.then(resolve)
.catch(reject);
});
}
async function calculate(stream, chunkSize) {
const dataSize = await getStreamSize(stream);
let sumOfSums = [];
let parts = 0;
let position = 0;
while (position < dataSize) {
let length = chunkSize;
if (position + chunkSize > dataSize) {
length = dataSize - position;
}
const sum = await md5sum(stream, position, length);
sumOfSums.push(sum);
parts++;
position += length;
}
let finalSum;
if (parts === 1) {
finalSum = sumOfSums[0];
} else {
finalSum = crypto.createHash('md5').update(Buffer.concat(sumOfSums)).digest();
}
let sumHex = finalSum.toString('hex');
if (parts > 1) {
sumHex += '-' + parts;
}
return sumHex;
}
function md5sum(stream, start, length) {
return new Promise((resolve, reject) => {
const hash = crypto.createHash('md5');
const buffer = Buffer.alloc(length);
const fd = fs.openSync(stream.path, 'r');
fs.read(fd, buffer, 0, length, start, (err, bytesRead, buf) => {
if (err) return reject(err);
hash.update(buf.slice(0, bytesRead));
fs.closeSync(fd);
resolve(hash.digest());
});
});
}
function getStreamSize(stream) {
return new Promise((resolve, reject) => {
fs.stat(stream.path, (err, stats) => {
if (err) return reject(err);
resolve(stats.size);
});
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment