Upload files
Ts.ED supports now the uploading files by default. We use Multer module to handle multipart/form-data from request.
TIP
Originally, multer is provided by Express.js, but Ts.ED implements a multer wrapper to support Koa.js platform based on the official @koa/multer module.
Configuration
By default, the directory used is ${projetRoot}/uploads. You can configure another directory on your Server settings.
import {Configuration} from "@tsed/di";
import "@tsed/platform-express";
import "@tsed/platform-multer/express"; // or "@tsed/platform-multer/koa" or "@tsed/platform-multer/fastify"
@Configuration({
multer: {
dest: `./../uploads`
// see multer options
}
})
export class Server {}Options
dest(string): The destination directory for the uploaded files.storage(StoreEngine): The storage engine to use for uploaded files.limits(Object): An object specifying the size limits of the following optional properties. This object is passed to busboy directly, and the details of properties can be found on https://github.com/mscdex/busboy.fieldNameSize(number): Max field name size (Default: 100 bytes).fieldSize(number): Max field value size (Default: 1MB).fields(number): Max number of non- file fields (Default: Infinity).fileSize(number): For multipart forms, the max file size (in bytes)(Default: Infinity).files(number): For multipart forms, the max number of file fields (Default: Infinity).parts(number): For multipart forms, the max number of parts (fields + files)(Default: Infinity).headerPairs(number): For multipart forms, the max number of headerkey => valuepairs to parse Default: 2000(same as node's http).
preservePath(boolean): Keep the full path of files instead of just the base name (Default: false).fileFilter(Function): Optional function to control which files are uploaded. This is called for every file that is processed.
Usage
Single file
A single file can be injected to your endpoint by using the MultipartFile decorator like this:
import {MulterOptions, MultipartFile, PlatformMulterFile} from "@tsed/platform-multer";
import {Post} from "@tsed/schema";
import {Controller} from "@tsed/di";
@Controller("/")
class MyCtrl {
@Post("/file")
private uploadFile1(@MultipartFile("file") file: PlatformMulterFile) {}
@Post("/file")
@MulterOptions({dest: "/other-dir"})
private uploadFile2(@MultipartFile("file") file: PlatformMulterFile) {}
}TIP
Many frontend code examples are available on the web and some of them don't work as expected. So, to help you, here is a short vanilla Javascript code example:
export async function loadFile(file) {
const formData = new FormData();
formData.append("file", file);
await fetch(`/rest/upload`, {
method: "POST",
headers: {
// don't set Content-Type: multipart/form-data. It's set automatically by fetch (same things with axios)
},
body: formData
});
}Multiple files
For multiple files, just use PlatformMulterFile[] annotation type. Ts.ED will understand that you want to inject a list of files even if your consumer only sends you one:
import {MultipartFile, PlatformMulterFile} from "@tsed/platform-multer";
import {Post} from "@tsed/schema";
import {Controller} from "@tsed/di";
@Controller("/")
class MyCtrl {
@Post("/files")
private uploadFile(@MultipartFile("files", 4) files: PlatformMulterFile[]) {
// multiple files with 4 as limits
}
}Middleware order and authentication
PlatformMulterMiddleware has a priority of -10. Lower priority values run first, so the upload middleware runs before a middleware declared with @UseBefore() at the default priority (0). This is intentional: it lets a @UseBefore() middleware access the uploaded file before the controller handler runs.
Authentication middleware
On an upload route, an authentication middleware with the default priority runs after Multer. As a result, an unauthenticated request can start uploading a file before it is rejected. Give the authentication middleware a priority lower than -10 so it runs before Multer.
For example, this controller uploads the file before AuthMiddleware checks the request:
import {Controller} from "@tsed/di";
import {UseBefore, Middleware} from "@tsed/platform-middlewares";
import {MultipartFile, PlatformMulterFile} from "@tsed/platform-multer";
import {Post} from "@tsed/schema";
@Middleware()
class AuthMiddleware {
use() {
// Check the request authentication
}
}
@Controller("/files")
class FilesController {
@Post("/")
@UseBefore(AuthMiddleware)
upload(@MultipartFile("file") file: PlatformMulterFile) {
return file;
}
}Set the middleware priority to -11 (or any value lower than -10) to authenticate the request before the file is handled by Multer:
import {Middleware} from "@tsed/platform-middlewares";
@Middleware({priority: -11})
class AuthMiddleware {
use() {
// Check the request authentication before the upload starts
}
}Use -10 only when the authentication middleware's relative order with PlatformMulterMiddleware is otherwise explicitly controlled. A lower value is the reliable choice when authentication must happen before an upload.