file-chunkify
Version:
289 lines (284 loc) • 9.67 kB
JavaScript
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
var __await = function(promise, isYieldStar) {
this[0] = promise;
this[1] = isYieldStar;
};
var __asyncGenerator = (__this, __arguments, generator) => {
var resume = (k, v, yes, no) => {
try {
var x = generator[k](v), isAwait = (v = x.value) instanceof __await, done = x.done;
Promise.resolve(isAwait ? v[0] : v).then((y) => isAwait ? resume(k === "return" ? k : "next", v[1] ? { done: y.done, value: y.value } : y, yes, no) : yes({ value: y, done })).catch((e) => resume("throw", e, yes, no));
} catch (e) {
no(e);
}
}, method = (k) => it[k] = (x) => new Promise((yes, no) => resume(k, x, yes, no)), it = {};
return generator = generator.apply(__this, __arguments), it[__knownSymbol("asyncIterator")] = () => it, method("next"), method("throw"), method("return"), it;
};
// src/index.ts
var index_exports = {};
__export(index_exports, {
saveChunk: () => saveChunk,
splitFile: () => splitFile
});
module.exports = __toCommonJS(index_exports);
// src/common.ts
function logMessage(message, isError = false, options) {
if (options == null ? void 0 : options.debugMode) {
isError ? console.error(message) : console.log(message);
}
}
// src/split-file.ts
function generateUUID() {
return `${Date.now()}-${Math.floor(Math.random() * 1e9)}`;
}
function validateParams({ file, chunkSize }) {
if (!(file instanceof File)) {
throw new Error("Invalid file: Expected a valid File object.");
}
if (!chunkSize || chunkSize <= 0) {
throw new Error("Invalid chunk size: Must be a positive number.");
}
}
function splitFile(_0) {
return __asyncGenerator(this, arguments, function* ({
file,
chunkSize = 5 * 1024 * 1024,
options
}) {
var _a, _b;
try {
validateParams({ file, chunkSize });
const totalChunks = Math.ceil(file.size / chunkSize);
if (totalChunks === 0) {
throw new Error("File size is too small to be split.");
}
const fileExtension = ((_b = (_a = file == null ? void 0 : file.name) == null ? void 0 : _a.split(".")) == null ? void 0 : _b.pop()) || "bin";
const fileName = `${generateUUID()}.${fileExtension}`;
let chunkNumber = 0;
let start = 0;
let end = chunkSize;
while (start < file.size) {
const chunk = file.slice(start, end);
yield {
chunk: new File([chunk], fileName),
chunkNumber,
totalChunks,
fileName,
progress: Math.ceil((chunkNumber + 1) / totalChunks * 100)
};
chunkNumber++;
start = end;
end = start + chunkSize;
}
} catch (err) {
logMessage(
`Error during file splitting: ${err.message}`,
true,
options
);
throw err;
}
});
}
// src/merge-file.ts
var import_fs = require("fs");
var import_path = __toESM(require("path"));
function validateParams2({
file,
chunkNumber,
totalChunks,
outputDir,
chunkDir
}) {
chunkNumber = Number(chunkNumber);
totalChunks = Number(totalChunks);
if (!file || !file.originalname || !file.buffer) {
throw new Error(
"Invalid file: Expected a valid file object with originalname and buffer."
);
}
if (isNaN(chunkNumber) || chunkNumber < 0) {
throw new Error(
`Invalid chunk number: Received ${chunkNumber}, expected a non-negative number.`
);
}
if (isNaN(totalChunks) || totalChunks <= 0 || chunkNumber >= totalChunks) {
throw new Error(
`Invalid totalChunks: Received ${totalChunks}, expected a positive number greater than chunkNumber.`
);
}
if (typeof outputDir !== "string" || typeof chunkDir !== "string") {
throw new Error(
"Invalid directory paths: outputDir and chunkDir must be valid strings."
);
}
}
function saveChunk(_0) {
return __async(this, arguments, function* ({
file,
chunkNumber,
totalChunks,
outputDir = "./uploads",
chunkDir = "./uploads/chunks",
options
}) {
try {
validateParams2({ file, chunkNumber, totalChunks, outputDir, chunkDir });
const extension = import_path.default.extname(file.originalname) || ".bin";
const fileName = import_path.default.basename(file.originalname, extension);
chunkNumber = Number(chunkNumber);
totalChunks = Number(totalChunks);
chunkDir = import_path.default.resolve(chunkDir);
outputDir = import_path.default.resolve(outputDir);
if (!(0, import_fs.existsSync)(chunkDir)) (0, import_fs.mkdirSync)(chunkDir, { recursive: true });
const chunkFilePath = import_path.default.join(
chunkDir,
`${fileName}.part_${chunkNumber}`
);
try {
(0, import_fs.writeFileSync)(chunkFilePath, file.buffer);
logMessage(
`Chunk ${chunkNumber + 1}/${totalChunks} saved: ${chunkFilePath}`,
false,
options
);
} catch (err) {
logMessage(`Error saving chunk ${chunkNumber}: ${err}`, true, options);
throw new Error("Failed to save chunk");
}
if (chunkNumber === totalChunks - 1) {
const mergedFilePath = yield mergeChunks({
fileName,
totalChunks,
outputDir,
chunkDir,
extension,
options
});
return {
success: true,
message: "All chunks uploaded and merged successfully",
mergedFilePath
};
}
return {
success: true,
message: `Chunk ${chunkNumber} uploaded successfully`
};
} catch (err) {
logMessage(
`Error merging chunks: ${err.message}`,
true,
options
);
return {
success: false,
message: err.message
};
}
});
}
function mergeChunks(_0) {
return __async(this, arguments, function* ({
fileName,
totalChunks,
outputDir,
chunkDir,
extension,
options
}) {
if (!(0, import_fs.existsSync)(outputDir)) (0, import_fs.mkdirSync)(outputDir, { recursive: true });
const finalFilePath = import_path.default.join(outputDir, `${fileName}${extension}`);
logMessage(`Merging chunks into: ${finalFilePath}`, false, options);
return new Promise((resolve, reject) => {
const writeStream = (0, import_fs.createWriteStream)(finalFilePath);
let currentChunk = 0;
writeStream.on("error", (err) => {
logMessage(`Error writing to final file: ${err}`, true, options);
reject(err);
});
writeStream.on("finish", () => {
logMessage("Merging completed successfully!", false, options);
resolve(finalFilePath);
});
const mergeNextChunk = () => {
if (currentChunk < totalChunks) {
const chunkFilePath = import_path.default.join(
chunkDir,
`${fileName}.part_${currentChunk}`
);
try {
if (!(0, import_fs.existsSync)(chunkFilePath))
throw new Error(`Missing chunk file: ${chunkFilePath}`);
const chunkBuffer = (0, import_fs.readFileSync)(chunkFilePath);
writeStream.write(chunkBuffer, () => {
(0, import_fs.unlinkSync)(chunkFilePath);
currentChunk++;
mergeNextChunk();
});
} catch (err) {
logMessage(`Error processing chunk: ${err}`, true, options);
writeStream.destroy();
reject(err);
}
} else {
writeStream.end();
}
};
mergeNextChunk();
});
});
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
saveChunk,
splitFile
});
;