note
Last checked with Wasp 0.24 and multer 2.1.1.
This guide depends on external libraries or services, so it may become outdated over time. We do our best to keep it up to date, but make sure to check their documentation for any changes.File Uploads
This guide shows you how to implement file uploads in your Wasp application using Multer.
Setting up File Uploadsโ
1. Install Multerโ
Install the Multer package and its types:
npm install multer
npm install --save-dev @types/multer
2. Define the API endpoint in main.wasp.tsโ
Create an API namespace with middleware configuration and the upload endpoint:
main.wasp.ts
import { api, apiNamespace, app, page, route } from "@wasp.sh/spec"
import { configureFileUploadMiddleware, uploadFile } from "./src/apis" with { type: "ref" }
import { MainPage } from "./src/MainPage" with { type: "ref" }
export default app({
// ...
spec: [
route("RootRoute", "/", page(MainPage)),
apiNamespace("/api/upload", { middlewareConfigFn: configureFileUploadMiddleware }),
api("POST", "/api/upload", uploadFile),
],
})
3. Create the API handlersโ
Create the middleware configuration and upload handler:
- JavaScript
- TypeScript
src/apis.js
import multer from "multer";
const upload = multer({ dest: "uploads/" });
export const configureFileUploadMiddleware = (config) => {
config.set("multer", upload.single("file"));
return config;
};
export const uploadFile = (req, res) => {
console.log(req.body);
console.log(req.file);
const file = req.file;
return res.json({
fileExists: !!file,
});
};
src/apis.ts
import type { MiddlewareConfigFn } from "wasp/server";
import type { UploadFile } from "wasp/server/api";
import multer from "multer";
const upload = multer({ dest: "uploads/" });
export const configureFileUploadMiddleware: MiddlewareConfigFn = (config) => {
config.set("multer", upload.single("file"));
return config;
};
export const uploadFile: UploadFile = (req, res) => {
console.log(req.body);
console.log(req.file);
const file = req.file!;
return res.json({
fileExists: !!file,
});
};
4. Create the upload formโ
Create a form component to handle file uploads:
- JavaScript
- TypeScript
src/MainPage.jsx
import { useState } from "react";
import { api } from "wasp/client/api";
export const MainPage = () => {
const [name, setName] = useState("");
const [file, setFile] = useState();
const handleSubmit = async (e) => {
e.preventDefault();
if (!file) return;
const formData = new FormData();
formData.append("name", name);
formData.append("file", file);
const data = await api.post("/api/upload", { body: formData }).json();
alert(JSON.stringify(data, null, 2));
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Name"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<input type="file" onChange={(e) => setFile(e.target.files?.[0])} />
<button type="submit">Upload</button>
</form>
);
};
src/MainPage.tsx
import { useState } from "react";
import { api } from "wasp/client/api";
export const MainPage = () => {
const [name, setName] = useState("");
const [file, setFile] = useState<File>();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!file) return;
const formData = new FormData();
formData.append("name", name);
formData.append("file", file);
const data = await api
.post("/api/upload", { body: formData })
.json<{ fileExists: boolean }>();
alert(JSON.stringify(data, null, 2));
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
placeholder="Name"
value={name}
onChange={(e) => setName(e.target.value)}
/>
<input type="file" onChange={(e) => setFile(e.target.files?.[0])} />
<button type="submit">Upload</button>
</form>
);
};
Customizing Upload Settingsโ
Change upload destinationโ
You can customize where files are stored:
- JavaScript
- TypeScript
const upload = multer({ dest: "my-custom-uploads/" });
const upload = multer({ dest: "my-custom-uploads/" });
Limit file sizeโ
Add file size limits:
- JavaScript
- TypeScript
const upload = multer({
dest: "uploads/",
limits: {
fileSize: 5 * 1024 * 1024, // 5MB limit
},
});
const upload = multer({
dest: "uploads/",
limits: {
fileSize: 5 * 1024 * 1024, // 5MB limit
},
});
Filter file typesโ
Only accept certain file types:
- JavaScript
- TypeScript
const upload = multer({
dest: "uploads/",
fileFilter: (req, file, cb) => {
if (file.mimetype.startsWith("image/")) {
cb(null, true);
} else {
cb(new Error("Only images are allowed"));
}
},
});
const upload = multer({
dest: "uploads/",
fileFilter: (req, file, cb) => {
if (file.mimetype.startsWith("image/")) {
cb(null, true);
} else {
cb(new Error("Only images are allowed"));
}
},
});
Handle multiple filesโ
To handle multiple file uploads:
- JavaScript
- TypeScript
export const configureFileUploadMiddleware = (config) => {
config.set("multer", upload.array("files", 10)); // Max 10 files
return config;
};
export const configureFileUploadMiddleware: MiddlewareConfigFn = (config) => {
config.set("multer", upload.array("files", 10)); // Max 10 files
return config;
};
For more options, see the Multer documentation.