@deconz-community/directus-extension-ddf-store
Version:
Extension for Directus to store DDF files in the database, used only by the Deconz Community
94 lines (74 loc) • 2.16 kB
text/typescript
import type { RequestHandler } from 'express'
import { createError } from '@directus/errors'
import Busboy from 'busboy'
const ContentTooLargeError = createError('CONTENT_TOO_LARGE', 'Uploaded content is too large.', 413)
const NoFileUploadedError = createError('INVALID_PAYLOAD', 'No files uploaded', 413)
export type BlobsPayload = Record<string, {
blob: Blob
meta: Record<string, string | boolean | null>
}>
export const multipartHandler: RequestHandler<object, any, BlobsPayload> = (req, _res, next) => {
if (req.is('multipart/form-data') === false)
return next()
let headers
if (req.headers['content-type']) {
headers = req.headers
}
else {
headers = {
...req.headers,
'content-type': 'application/octet-stream',
}
}
const busboy = Busboy({
headers,
defParamCharset: 'utf8',
limits: {
fileSize: 5000000,
},
})
let currentMeta: BlobsPayload[string]['meta'] = {}
const payload: BlobsPayload = {}
busboy.on('field', (fieldname, val) => {
let fieldValue: string | null | boolean = val
if (typeof fieldValue === 'string' && fieldValue.trim() === 'null')
fieldValue = null
if (typeof fieldValue === 'string' && fieldValue.trim() === 'false')
fieldValue = false
if (typeof fieldValue === 'string' && fieldValue.trim() === 'true')
fieldValue = true
currentMeta[fieldname] = fieldValue
})
busboy.on('file', (uploadUUID, fileStream) => {
fileStream.on('limit', () => {
next(ContentTooLargeError)
})
const chunks: BlobPart[] = []
fileStream.on('data', (data: BlobPart) => {
chunks.push(data)
}).on('close', () => {
payload[uploadUUID] = {
blob: new Blob(chunks),
meta: structuredClone(currentMeta),
}
currentMeta = {}
})
return undefined
})
busboy.on('error', (error: Error) => {
console.error(error)
next(error)
})
busboy.on('close', () => {
if (Object.keys(payload).length === 0)
next(NoFileUploadedError)
req.body = payload
return next()
})
try {
req.pipe(busboy)
}
catch (e) {
console.error(e)
}
}