fcsc_ipi_backend/app/middleware/csvUpload.middleware.js

117 lines
3.4 KiB
JavaScript

const multer = require("multer");
const { UPLOAD_DIR } = require("../config/upload.config");
const CSV_UPLOAD_FIELD = "file";
const upload = multer({
dest: UPLOAD_DIR,
limits: { fileSize: 10 * 1024 * 1024 },
});
function respondCsvUploadError(res, statusCode, message, extra = {}) {
return res.status(statusCode).json({
status: "failed",
message,
...extra,
});
}
/**
* Parses multipart upload and sets req.file from form field "file".
* Returns helpful errors when Swagger/Postman sends the wrong shape.
*/
function handleCsvUpload(req, res, next) {
upload.any()(req, res, (err) => {
if (err) {
if (err.code === "LIMIT_FILE_SIZE") {
return respondCsvUploadError(
res,
400,
"CSV file is too large. Maximum allowed size is 10 MB."
);
}
if (err.code === "LIMIT_UNEXPECTED_FILE") {
return respondCsvUploadError(
res,
400,
`Unexpected file field "${err.field}". Use form field name "${CSV_UPLOAD_FIELD}" for the CSV.`,
{ expected_field: CSV_UPLOAD_FIELD, received_field: err.field }
);
}
return respondCsvUploadError(
res,
400,
"Could not read uploaded file. Please upload a valid .csv file.",
{ detail: err.message }
);
}
const files = Array.isArray(req.files) ? req.files : [];
if (files.length === 0) {
const contentType = req.headers["content-type"] || "";
if (!contentType.includes("multipart/form-data")) {
return respondCsvUploadError(
res,
400,
"CSV upload must use multipart/form-data, not JSON.",
{
hint: `Send your .csv in form field "${CSV_UPLOAD_FIELD}". In Swagger: choose the file under "${CSV_UPLOAD_FIELD}" before Execute.`,
expected_field: CSV_UPLOAD_FIELD,
received_content_type: contentType || "(missing)",
}
);
}
return respondCsvUploadError(
res,
400,
`No CSV file received. Attach a .csv file to form field "${CSV_UPLOAD_FIELD}".`,
{
hint:
'In Swagger UI: click "Try it out" → use the file picker for "' +
CSV_UPLOAD_FIELD +
'" (e.g. hs-codes-sample.csv) → then Execute. Do not leave the file field empty.',
expected_field: CSV_UPLOAD_FIELD,
example_curl:
'curl -F "file=@hs-codes-sample.csv;type=text/csv" ...',
}
);
}
const csvFile = files.find((f) => f.fieldname === CSV_UPLOAD_FIELD);
if (!csvFile) {
const receivedFields = [...new Set(files.map((f) => f.fieldname))];
return respondCsvUploadError(
res,
400,
`CSV must use form field "${CSV_UPLOAD_FIELD}", but received: ${receivedFields.join(", ")}.`,
{
hint: `Change the form field name to "${CSV_UPLOAD_FIELD}" and upload again.`,
expected_field: CSV_UPLOAD_FIELD,
received_fields: receivedFields,
}
);
}
if (files.length > 1) {
return respondCsvUploadError(
res,
400,
"Only one CSV file can be uploaded per request.",
{
hint: `Send a single file in field "${CSV_UPLOAD_FIELD}".`,
received_file_count: files.length,
}
);
}
req.file = csvFile;
return next();
});
}
module.exports = { handleCsvUpload, CSV_UPLOAD_FIELD };