Created
October 14, 2021 13:45
-
-
Save srivatsav/37e5ce7d76f12413b2c8743d07b591ac to your computer and use it in GitHub Desktop.
File Stream Splitter.
This file contains 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
const fs = require("fs"); | |
const splitFileReadStream = (readStream, maxFileSize, filePath, callback) => { | |
if(maxFileSize <= 0) { | |
throw new Error("Invlaid file size.") | |
} | |
const fileChunks = []; | |
const outputStream = (splitOffset) => { | |
let fileSplitPath = generateFilePath(filePath, splitOffset) | |
return fs.createWriteStream(fileSplitPath); | |
} | |
splitStream(outputStream, readStream, maxFileSize, (error, writeStreams) => { | |
writeStreams.forEach((writeStream) => fileChunks.push(writeStream["path"])); | |
callback(error, fileChunks); | |
}); | |
} | |
const splitStream = (outputStream, fileStream, maxFileSize, callback) => { | |
let chunkNumber = 0; | |
let currentFileSize = 0; | |
let currentOutputWriteStream; | |
let noOfStreamsWritten = 0; | |
let fileStreamStart = false; | |
let fileStreamEnd = false; | |
let error = null; | |
const outputStreams = []; | |
const {highWaterMark: defaultChunkSize } = fileStream._readableState; | |
fileStream.on('readable', () => { | |
let fileChunk; | |
while((fileChunk=fileStream.read(Math.min(maxFileSize - currentFileSize, defaultChunkSize)))!==null) { | |
if(!fileStreamStart) { | |
createChunkOutPutWriteStream(); | |
fileStreamStart = true; | |
} | |
if(fileChunk.length > maxFileSize) { | |
throw new Error("Failed chunking FILE into given maxFileSize."); | |
} | |
currentOutputWriteStream.write(fileChunk); | |
currentFileSize+=fileChunk.length; | |
if(currentFileSize==maxFileSize) { | |
endChunkWriteStream(); | |
} | |
} | |
}); | |
// creating output stream for each individual chunk in a file partition. | |
const createChunkOutPutWriteStream = () => { | |
currentOutputWriteStream = outputStream(chunkNumber); // returns a write stream for the file chunk. | |
currentOutputWriteStream.on('finish', () => { | |
noOfStreamsWritten++; | |
if(fileStreamEnd && (noOfStreamsWritten==chunkNumber)) { | |
callback(error, outputStreams); | |
} | |
}); | |
outputStreams.push(currentOutputWriteStream); | |
chunkNumber++; | |
} | |
const endChunkWriteStream = () => { | |
currentOutputWriteStream.end(); | |
currentOutputWriteStream=null; | |
currentFileSize=0; | |
fileStreamStart=false; | |
} | |
fileStream.on('end', () => { | |
if(currentOutputWriteStream) | |
endChunkWriteStream() | |
fileStreamEnd=true; | |
}); | |
} | |
const generateFilePath=(baseName, n)=>{ | |
return `${baseName}-split-${n}`; | |
} | |
module.exports = { | |
splitFileReadStream | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment