UNPKG

@fastify/multipart

Version:
189 lines (162 loc) 5.87 kB
/* eslint-disable @typescript-eslint/no-unused-expressions */ import fastify from 'fastify' import fastifyMultipart, { MultipartValue, MultipartFields, MultipartFile } from '..' import * as util from 'node:util' import { pipeline } from 'node:stream' import * as fs from 'node:fs' import { expectError, expectType } from 'tsd' import { FastifyErrorConstructor } from '@fastify/error' import { BusboyConfig, BusboyFileStream } from '@fastify/busboy' const pump = util.promisify(pipeline) const runServer = async () => { const app = fastify() app.register(fastifyMultipart, { preservePath: true, // field inherited from `BusboyConfig` interface attachFieldsToBody: true, limits: { parts: 500 }, onFile: (part: MultipartFile) => { console.log(part) } }) // usage app.post('/', async (req, reply) => { expectType<Promise<FormData>>(req.formData()) const data = await req.file() if (data == null) throw new Error('missing file') expectType<'file'>(data.type) expectType<BusboyFileStream>(data.file) expectType<boolean>(data.file.truncated) expectType<MultipartFields>(data.fields) expectType<string>(data.fieldname) expectType<string>(data.filename) expectType<string>(data.encoding) expectType<string>(data.mimetype) const field = data.fields.myField if (field === undefined) { // field missing from the request } else if (Array.isArray(field)) { // multiple fields with the same name } else if (field.type === 'file') { // field containing a file field.file.resume() } else { // field containing a value field.fields.value } await pump(data.file, fs.createWriteStream(data.filename)) reply.send() }) // Multiple fields including scalar values app.post<{ Body: { file: MultipartFile, foo: MultipartValue<string> } }>('/upload/stringvalue', async (req, reply) => { expectError(req.body.foo.file) expectType<'field'>(req.body.foo.type) expectType<string>(req.body.foo.value) expectType<BusboyFileStream>(req.body.file.file) expectType<'file'>(req.body.file.type) reply.send() }) app.post<{ Body: { file: MultipartFile, num: MultipartValue<number> } }>('/upload/stringvalue', async (req, reply) => { expectType<number>(req.body.num.value) reply.send() // file is a file expectType<BusboyFileStream>(req.body.file.file) expectError(req.body.file.value) }) // busboy app.post('/', async function (req, reply) { const data = await req.file({ limits: { fileSize: 1000, parts: 500 }, throwFileSizeLimit: true, sharedSchemaId: 'schemaId', isPartAFile: (fieldName, contentType, fileName) => { expectType<string | undefined>(fieldName) expectType<string | undefined>(contentType) expectType<string | undefined>(fileName) return true } }) if (!data) throw new Error('missing file') await pump(data.file, fs.createWriteStream(data.filename)) reply.send() }) // handle multiple file streams app.post('/', async (req, reply) => { const parts = req.files({ limits: { fileSize: 1000, parts: 500 }, throwFileSizeLimit: true, sharedSchemaId: 'schemaId', isPartAFile: (fieldName, contentType, fileName) => { expectType<string | undefined>(fieldName) expectType<string | undefined>(contentType) expectType<string | undefined>(fileName) return true } }) for await (const part of parts) { await pump(part.file, fs.createWriteStream(part.filename)) } reply.send() }) // handle multiple file streams and fields app.post('/upload/raw/any', async function (req, reply) { const parts = req.parts() for await (const part of parts) { if (part.type === 'file') { await pump(part.file, fs.createWriteStream(part.filename)) } else { console.log(part.value) } } reply.send() }) // accumulate whole file in memory app.post('/upload/raw/any', async function (req, reply) { const data = await req.file() if (!data) throw new Error('missing file') expectType<Buffer>(await data.toBuffer()) // upload to S3 reply.send() }) // upload files to disk and work with temporary file paths app.post('/upload/files', async function (req, reply) { // stores files to tmp dir and return files const files = await req.saveRequestFiles() files[0].type // "file" files[0].filepath files[0].fieldname files[0].filename files[0].encoding files[0].mimetype files[0].fields // other parsed parts reply.send() }) // upload files to disk with busboy options app.post('/upload/files', async function (req, reply) { const options: Partial<BusboyConfig> = { limits: { fileSize: 1000 } } await req.saveRequestFiles(options) reply.send() }) // access all errors app.post('/upload/files', async function (_req, reply) { const { FilesLimitError } = app.multipartErrors expectType<FastifyErrorConstructor>(app.multipartErrors.FieldsLimitError) expectType<FastifyErrorConstructor>(app.multipartErrors.FilesLimitError) expectType<FastifyErrorConstructor>(app.multipartErrors.InvalidMultipartContentTypeError) expectType<FastifyErrorConstructor>(app.multipartErrors.PartsLimitError) expectType<FastifyErrorConstructor>(app.multipartErrors.PrototypeViolationError) expectType<FastifyErrorConstructor>(app.multipartErrors.RequestFileTooLargeError) // test instanceof Error const a = new FilesLimitError() if (a instanceof FilesLimitError) { console.log('FilesLimitError occurred.') } reply.send() }) await app.ready() } runServer().then( console.log.bind(console, 'Success'), console.error.bind(console, 'Error') )