117 lines
3.4 KiB
JavaScript
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 };
|