This repository has been archived on 2024-10-29. You can view files and clone it, but cannot push or open issues or pull requests.
2023-01-11 00:24:19 +01:00

72 lines
2.0 KiB
TypeScript

import fs from 'node:fs'
import { URL } from 'node:url'
import { randomUUID } from 'node:crypto'
import type { FastifyInstance, FastifyRequest } from 'fastify'
import type { SavedMultipartFile } from '@fastify/multipart'
import { API_URL, ROOT_URL } from '../configurations.js'
export interface UploadFileOptions {
folderInUploadsFolder: 'guilds' | 'messages' | 'users'
request: FastifyRequest
fastify: FastifyInstance
/** in megabytes */
maximumFileSize: number
supportedFileMimetype?: string[]
}
export interface UploadFileResult {
pathToStoreInDatabase: string
mimetype: string
}
export const uploadFile = async (
options: UploadFileOptions
): Promise<UploadFileResult> => {
const {
fastify,
request,
folderInUploadsFolder,
maximumFileSize,
supportedFileMimetype
} = options
let files: SavedMultipartFile[] = []
try {
files = await request.saveRequestFiles({
limits: {
files: 1,
fileSize: maximumFileSize * 1024 * 1024
}
})
} catch (error) {
throw fastify.httpErrors.requestHeaderFieldsTooLarge(
`File should be less than ${maximumFileSize}mb.`
)
}
const file = files[0]
if (files.length !== 1 || file == null) {
throw fastify.httpErrors.badRequest('You must upload at most one file.')
}
if (
supportedFileMimetype != null &&
!supportedFileMimetype.includes(file.mimetype)
) {
throw fastify.httpErrors.badRequest(
`The file must have a valid type (${supportedFileMimetype.join(', ')}).`
)
}
const splitedMimetype = file.mimetype.split('/')
const fileExtension = splitedMimetype[1]
if (fileExtension == null) {
throw fastify.httpErrors.badRequest('The file extension is not valid.')
}
const filePath = `uploads/${folderInUploadsFolder}/${randomUUID()}.${fileExtension}`
const fileURL = new URL(filePath, ROOT_URL)
const pathToStoreInDatabase = `${API_URL}/${filePath}`
await fs.promises.copyFile(file.filepath, fileURL)
return { pathToStoreInDatabase, mimetype: file.mimetype }
}