Last active
December 19, 2021 07:10
-
-
Save badsyntax/340d2241217551ee4645e48d59f8daf6 to your computer and use it in GitHub Desktop.
Generate an S3 ETAG for multipart uploads in Node.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Generate an S3 ETAG for multipart uploads in Node.js | |
* An implementation of this algorithm: https://stackoverflow.com/a/19896823/492325 | |
* Author: Richard Willis <[email protected]> | |
*/ | |
import fs from 'node:fs'; | |
import crypto, { BinaryLike } from 'node:crypto'; | |
const defaultPartSizeInBytes = 5 * 1024 * 1024; // 5MB | |
function md5(contents: string | BinaryLike): string { | |
return crypto.createHash('md5').update(contents).digest('hex'); | |
} | |
export function getS3Etag( | |
filePath: string, | |
partSizeInBytes = defaultPartSizeInBytes | |
): string { | |
const { size: fileSizeInBytes } = fs.statSync(filePath); | |
let parts = Math.floor(fileSizeInBytes / partSizeInBytes); | |
if (fileSizeInBytes % partSizeInBytes > 0) { | |
parts += 1; | |
} | |
const fileDescriptor = fs.openSync(filePath, 'r'); | |
let totalMd5 = ''; | |
for (let part = 0; part < parts; part++) { | |
const skipBytes = partSizeInBytes * part; | |
const totalBytesLeft = fileSizeInBytes - skipBytes; | |
const bytesToRead = Math.min(totalBytesLeft, partSizeInBytes); | |
const buffer = Buffer.alloc(bytesToRead); | |
fs.readSync(fileDescriptor, buffer, 0, bytesToRead, skipBytes); | |
totalMd5 += md5(buffer); | |
} | |
const combinedHash = md5(Buffer.from(totalMd5, 'hex')); | |
const etag = `${combinedHash}-${parts}`; | |
return etag; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See project for updates: https://github.com/badsyntax/s3-etag