62 lines
1.8 KiB
TypeScript
Executable File
62 lines
1.8 KiB
TypeScript
Executable File
import {UploadedFile} from '../uploaded-file';
|
|
import {message} from '../../i18n/message';
|
|
import {prettyBytes} from '../utils/pretty-bytes';
|
|
import {MessageDescriptor} from '../../i18n/message-descriptor';
|
|
import match from 'mime-match';
|
|
|
|
export interface Restrictions {
|
|
maxFileSize?: number;
|
|
allowedFileTypes?: string[];
|
|
blockedFileTypes?: string[];
|
|
}
|
|
|
|
export function validateUpload(
|
|
file: UploadedFile,
|
|
restrictions?: Restrictions
|
|
): MessageDescriptor | void {
|
|
if (!restrictions) return;
|
|
|
|
const {maxFileSize, allowedFileTypes, blockedFileTypes} = restrictions;
|
|
|
|
if (maxFileSize && file.size != null && file.size > maxFileSize) {
|
|
return message('`:file` exceeds maximum allowed size of :size', {
|
|
values: {file: file.name, size: prettyBytes(maxFileSize)},
|
|
});
|
|
}
|
|
|
|
if (allowedFileTypes?.length) {
|
|
if (!fileMatchesTypes(file, allowedFileTypes)) {
|
|
return message('This file type is not allowed');
|
|
}
|
|
}
|
|
|
|
if (blockedFileTypes?.length) {
|
|
if (fileMatchesTypes(file, blockedFileTypes)) {
|
|
return message('This file type is not allowed');
|
|
}
|
|
}
|
|
}
|
|
|
|
function fileMatchesTypes(file: UploadedFile, types: string[]): boolean {
|
|
return (
|
|
types
|
|
// support multiple file types in a string (video/mp4,audio/mp3,image/png)
|
|
.map(type => type.split(','))
|
|
.flat()
|
|
.some(type => {
|
|
// check if this is a mime-type
|
|
if (type.includes('/')) {
|
|
if (!file.mime) return false;
|
|
return match(file.mime.replace(/;.*?$/, ''), type);
|
|
}
|
|
|
|
// otherwise this is likely an extension
|
|
const extension = type.replace('.', '').toLowerCase();
|
|
if (extension && file.extension) {
|
|
return file.extension.toLowerCase() === extension;
|
|
}
|
|
return false;
|
|
})
|
|
);
|
|
}
|