Skip to content

Commit

Permalink
Added validation for CSV and JSON file type
Browse files Browse the repository at this point in the history
  • Loading branch information
sushantpatil1214 committed Nov 19, 2024
1 parent 31a047f commit 8dda3c3
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 24 deletions.
67 changes: 48 additions & 19 deletions src/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import logger from '../logger';
import fs from 'fs';
import path from 'path';
import { uploadToMinio } from '../utils/minioClient';
import e from 'express';
const routes = express.Router();

const bodySizeLimit = getConfig().bodySizeLimit;
Expand All @@ -31,6 +32,20 @@ const saveCsvToTmp = (fileBuffer: Buffer, fileName: string): string => {
return fileUrl;
};

const isValidFileType = (file: Express.Multer.File): boolean => {
const validMimeTypes = ['text/csv', 'application/json'];
return validMimeTypes.includes(file.mimetype);
};

function validateJsonFile(buffer: Buffer): boolean {
try {
JSON.parse(buffer.toString());
return true;
} catch {
return false;
}
}

routes.post('/upload', upload.single('file'), async (req, res) => {
const file = req.file;
const bucket = req.query.bucket;
Expand All @@ -45,30 +60,44 @@ routes.post('/upload', upload.single('file'), async (req, res) => {
return res.status(400).send('No bucket provided');
}

const headers = getCsvHeaders(file.buffer);

if (!headers) {
return res.status(400).send('Invalid file type, please upload a valid CSV file');
if (!isValidFileType(file)) {
logger.error(`Invalid file type: ${file.mimetype}`);
return res.status(400).send('Invalid file type. Please upload either a CSV or JSON file');
}
const fileUrl = saveCsvToTmp(file.buffer, file.originalname);
logger.info(`file created: ${file.originalname}`);

try {
const uploadResult = await uploadToMinio(fileUrl, file.originalname, bucket as string);
// Clean up the temporary file
fs.unlinkSync(fileUrl);
// For CSV files, validate headers
if (file.mimetype === 'text/csv') {
const headers = getCsvHeaders(file.buffer);
if (!headers) {
return res.status(400).send('Invalid CSV file format');
}
try {
const fileUrl = saveCsvToTmp(file.buffer, file.originalname);
const uploadResult = await uploadToMinio(fileUrl, file.originalname, bucket as string, file.mimetype);
// Clean up the temporary file
fs.unlinkSync(fileUrl);

if (uploadResult) {
return res.status(201).send(`File ${file.originalname} uploaded in bucket ${bucket}`);
} else {
return res.status(400).send(`Object ${file.originalname} already exists in bucket ${bucket}`);
if (uploadResult) {
return res.status(201).send(`File ${file.originalname} uploaded in bucket ${bucket}`);
} else {
return res.status(400).send(`Object ${file.originalname} already exists in bucket ${bucket}`);
}
} catch (error) {
// Clean up the temporary file in case of error
fs.unlinkSync(fileUrl);
logger.error('Error uploading file to Minio:', error);
return res.status(500).send('Error uploading file');
}
} else if (file.mimetype === 'application/json') {
if (!validateJsonFile(file.buffer)) {
return res.status(400).send('Invalid JSON file format');
}
} catch (error) {
// Clean up the temporary file in case of error
fs.unlinkSync(fileUrl);
logger.error('Error uploading file to Minio:', error);
return res.status(500).send('Error uploading file');

return res.status(200).send('JSON file is valid - Future implementation');
} else {
return res.status(400).send('Invalid file type. Please upload either a CSV or JSON file');
}

});

export default routes;
10 changes: 5 additions & 5 deletions src/utils/minioClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const {endPoint, port, useSSL, bucketRegion, accessKey, secretKey, prefix, suffi
* @param {Object} [customMetadata={}] - Optional custom metadata
* @returns {Promise<void>}
*/
export async function uploadToMinio(sourceFile: string, destinationObject: string, bucket: string, customMetadata = {}) {
export async function uploadToMinio(sourceFile: string, destinationObject: string, bucket: string, fileType: string, customMetadata = {}) {
const minioClient = new Minio.Client({
endPoint,
port,
Expand All @@ -29,12 +29,12 @@ export async function uploadToMinio(sourceFile: string, destinationObject: strin


try {
const fileExists = await checkCsvFileExists(destinationObject, bucket);
const fileExists = await checkFileExists(destinationObject, bucket, fileType);
if (fileExists) {
return false;
} else {
const metaData = {
'Content-Type': 'text/plain',
'Content-Type': fileType,
'X-Upload-Id': crypto.randomUUID(),
...customMetadata
};
Expand All @@ -55,7 +55,7 @@ export async function uploadToMinio(sourceFile: string, destinationObject: strin
* @param {string} bucket - Bucket name
* @returns {Promise<boolean>} - Returns true if file exists, false otherwise
*/
export async function checkCsvFileExists(fileName: string, bucket: string): Promise<boolean> {
export async function checkFileExists(fileName: string, bucket: string, fileType: string): Promise<boolean> {
const minioClient = new Minio.Client({
endPoint,
port,
Expand All @@ -74,7 +74,7 @@ export async function checkCsvFileExists(fileName: string, bucket: string): Prom

// Get object stats to check if file exists
const stats = await minioClient.statObject(bucket, fileName); // Optionally verify it's a CSV file by checking Content-Type
if (stats.metaData && stats.metaData['content-type']) {
if (stats.metaData && stats.metaData['content-type'] === fileType) {
logger.info(`File ${fileName} exists in bucket ${bucket}`);
return true;
} else {
Expand Down

0 comments on commit 8dda3c3

Please sign in to comment.