@d3vtool/kazejs
Version:
A flexible Node.js web framework built with TypeScript, focusing on dependency injection, routing, middleware, and schema validation. Supports dynamic routes, global middleware, static files, and customizable error handling for scalable apps.
76 lines (75 loc) • 3.59 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.fileUpload = fileUpload;
function fileUpload(options) {
return function (ctx, next) {
const contentType = ctx.req.headers["content-type"];
if (!contentType ||
!contentType?.includes("multipart/form-data")) {
return next();
}
let chunks = [];
ctx.req.on("data", (chunk) => {
chunks.push(chunk);
});
ctx.req.on("end", () => {
const body = Buffer.concat(chunks);
const boundary = ctx.req.headers['content-type'].split('boundary=')[1];
const boundaryString = `--${boundary}`;
const bodyStr = body.toString('binary');
const parts = bodyStr.split(boundaryString);
const [withFilename, withoutFilename] = parts.reduce(([withFilename, withoutFilename], part) => {
if (part.includes('filename')) {
withFilename.push(part);
}
else {
withoutFilename.push(part);
}
return [withFilename, withoutFilename];
}, [[], []]);
if (withFilename.length > 0) {
ctx.req.files = [];
for (let idx = 0; idx < withFilename.length; ++idx) {
const [fileInfoStr, _] = withFilename[idx].split("\r\n\r\n");
const fileInfo = fileInfoStr.split("\r\n");
fileInfo.shift(); // discard '' empty str;
const [contentDispositionStr, contentType] = fileInfo;
const fieldName = contentDispositionStr.match(/name="([^"]+)"/)[1];
const fileName = contentDispositionStr.match(/filename="([^"]+)"/)[1];
const mimeType = contentType.split(": ").pop();
const fileDataStart = withFilename[idx].indexOf('\r\n\r\n') + 4;
const fileDataEnd = withFilename[idx].lastIndexOf('\r\n');
const startIndex = bodyStr.indexOf(withFilename[idx]) + fileDataStart;
const endIndex = bodyStr.indexOf(withFilename[idx]) + fileDataEnd;
const fileSize = endIndex - startIndex;
if (options?.limit && fileSize > options.limit ||
options?.acceptedMimeType && !options.acceptedMimeType.includes(mimeType)) {
continue;
}
const fileBuffer = body.subarray(startIndex, endIndex);
const file = {
fieldName,
fileName: options?.fileNameMutateFn ?
options.fileNameMutateFn(fileName) : fileName,
fileSize,
fileBuffer,
mimeType,
};
ctx.req.files?.push(file);
}
}
if (withoutFilename.length > 0) {
ctx.req.body = {};
withoutFilename.shift();
withoutFilename.pop();
for (let idx = 0; idx < withoutFilename.length; ++idx) {
let [fieldInfoStr, fieldData] = withoutFilename[idx].split("\r\n\r\n");
const fieldName = fieldInfoStr.match(/name="([^"]+)"/)[1];
fieldData = fieldData.replaceAll("\r\n", "");
ctx.req.body[fieldName] = fieldData;
}
}
next();
});
};
}