Skip to content

Commit f01a714

Browse files
committed
fix: Correct status code and message returned on invalid file upload
1 parent 569b7d9 commit f01a714

File tree

2 files changed

+45
-10
lines changed

2 files changed

+45
-10
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { HttpStatus, UnsupportedMediaTypeException } from '@nestjs/common'
2+
3+
/**
4+
* Custom exception thrown when file validation fails.
5+
* This exception provides a structured error response for unsupported or invalid file types.
6+
*/
7+
export class FileValidationException extends UnsupportedMediaTypeException {
8+
/**
9+
* Constructor.
10+
*
11+
* @param message - The detailed error message describing the validation failure
12+
* @param fileName - The name of the file that failed validation
13+
*/
14+
constructor(message: string, fileName = 'file') {
15+
super({
16+
statusCode: HttpStatus.UNSUPPORTED_MEDIA_TYPE,
17+
message: {
18+
property: fileName,
19+
constraints: {
20+
isValidFile: false,
21+
},
22+
},
23+
error: message,
24+
})
25+
}
26+
}

apps/api/src/common/files.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import path from 'path'
2+
import { FileValidationException } from './exception/file-validation.exception'
23

34
interface File {
45
fieldname: string
@@ -13,9 +14,11 @@ interface File {
1314
}
1415

1516
/**
16-
* The function is used to validate the type of a file using the file extension and MIME type
17+
* The function is used to validate the type of file using the file extension and MIME type
1718
* @param file object that represent file
1819
* @param cb callback function which indicates whether file is accepted or not
20+
*
21+
* @throws FileValidationException if the file does not pass validation
1922
*/
2023
export function validateFileType(
2124
file: File,
@@ -33,21 +36,27 @@ export function validateFileType(
3336
'application/vnd.ms-excel',
3437
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
3538
]
39+
40+
let filename = file.originalname
41+
let extension = path.extname(filename).toLowerCase()
42+
if (extension == '') {
43+
filename = file.filename
44+
// for the expense files, the original filename is encoded in base64
45+
extension = path.extname(filename).toLowerCase()
46+
}
47+
3648
if (!mimeAllowlist.includes(file.mimetype)) {
37-
return cb(new Error('File mime type is not allowed'), false)
49+
return cb(new FileValidationException('File mime type is not allowed', filename), false)
3850
}
3951

4052
const allowedExtensions = /txt|json|pdf|jpeg|jpg|png|xml|xlsx|xls|docx/
4153

42-
const filename = file.originalname
43-
let ext = path.extname(filename).toLowerCase()
44-
if (ext == '') {
45-
// for the expense files, the original filename is encoded in base64
46-
ext = path.extname(file.filename).toLowerCase()
47-
}
48-
const isExtensionSupported = allowedExtensions.test(ext)
54+
const isExtensionSupported = allowedExtensions.test(extension)
4955
if (!isExtensionSupported) {
50-
return cb(new Error('File extension is not allowed: ' + file.filename), false)
56+
return cb(
57+
new FileValidationException('File extension is not allowed: ' + filename, filename),
58+
false,
59+
)
5160
}
5261

5362
cb(null, true)

0 commit comments

Comments
 (0)