You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							178 lines
						
					
					
						
							5.2 KiB
						
					
					
				
			
		
		
	
	
							178 lines
						
					
					
						
							5.2 KiB
						
					
					
				| import fastify from 'fastify'
 | |
| import fastifyMultipart from '..'
 | |
| import { Multipart, MultipartFields, MultipartFile } from '..'
 | |
| import * as util from 'util'
 | |
| import { pipeline, Readable } from 'stream'
 | |
| import * as fs from '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, {
 | |
|     addToBody: true,
 | |
|     sharedSchemaId: 'sharedId',
 | |
|     throwFileSizeLimit: false,
 | |
|     // stream should be of type streams.Readable
 | |
|     // body should be of type fastifyMulipart.Record<string, BodyEntry>
 | |
|     onFile: (fieldName: string, stream: any, filename: string, encoding: string, mimetype: string, body: Record<string, any>) => {
 | |
|       console.log(fieldName, stream, filename, encoding, mimetype, body)
 | |
|     },
 | |
|     limits: {
 | |
|       fieldNameSize: 200,
 | |
|       fieldSize: 200,
 | |
|       fields: 200,
 | |
|       fileSize: 200,
 | |
|       files: 2,
 | |
|       headerPairs: 200
 | |
|     }
 | |
|   })
 | |
| 
 | |
|   app.register(fastifyMultipart, {
 | |
|     attachFieldsToBody: true,
 | |
|     onFile: (part: MultipartFile) => {
 | |
|       console.log(part)
 | |
|     }
 | |
|   })
 | |
| 
 | |
|   app.get('/path', (request) => {
 | |
|     const isMultiPart = request.isMultipart()
 | |
|     request.multipart((field, file, filename, encoding, mimetype) => {
 | |
|       console.log(field, file, filename, encoding, mimetype, isMultiPart)
 | |
|     }, (err) => {
 | |
|       throw err
 | |
|     }, {
 | |
|       limits: {
 | |
|         fileSize: 10000
 | |
|       }
 | |
|     })
 | |
|   })
 | |
| 
 | |
|   // usage
 | |
|   app.post('/', async (req, reply) => {
 | |
|     const data = await req.file()
 | |
| 
 | |
|     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)
 | |
| 
 | |
|     await pump(data.file, fs.createWriteStream(data.filename))
 | |
| 
 | |
|     reply.send()
 | |
|   })
 | |
| 
 | |
|   // Multiple fields including scalar values
 | |
|   app.post<{Body: {file: Multipart, foo: Multipart<string>}}>('/upload/stringvalue', async (req, reply) => {
 | |
|     expectError(req.body.foo.file);
 | |
|     expectType<string>(req.body.foo.value);
 | |
| 
 | |
|     expectType<BusboyFileStream>(req.body.file.file)
 | |
|     expectError(req.body.file.value);
 | |
|     reply.send();
 | |
|   })
 | |
| 
 | |
|   app.post<{Body: {file: Multipart, num: Multipart<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 options: Partial<BusboyConfig> = { limits: { fileSize: 1000 } };
 | |
|     const data = await req.file(options)
 | |
|     await pump(data.file, fs.createWriteStream(data.filename))
 | |
|     reply.send()
 | |
|   })
 | |
| 
 | |
|   // handle multiple file streams
 | |
|   app.post('/', async (req, reply) => {
 | |
|     const parts = req.files()
 | |
|     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.file) {
 | |
|         await pump(part.file, fs.createWriteStream(part.filename))
 | |
|       } else {
 | |
|         console.log(part)
 | |
|       }
 | |
|     }
 | |
|     reply.send()
 | |
|   })
 | |
| 
 | |
|   // accumulate whole file in memory
 | |
|   app.post('/upload/raw/any', async function (req, reply) {
 | |
|     const data = await req.file()
 | |
|     const 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].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')
 | |
| )
 |