web/docs/guides/integrations/file-upload.md
This guide shows you how to implement file uploads in your Wasp application using Multer.
Install the Multer package and its types:
npm install multer
npm install --save-dev @types/multer
Create an API namespace with middleware configuration and the upload endpoint:
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)),
// highlight-start
apiNamespace("/api/upload", { middlewareConfigFn: configureFileUploadMiddleware }),
api("POST", "/api/upload", uploadFile),
// highlight-end
],
})
Create the middleware configuration and upload handler:
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,
});
};
Create a form component to handle file uploads:
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>
);
};
You can customize where files are stored:
const upload = multer({ dest: "my-custom-uploads/" });
Add file size limits:
const upload = multer({
dest: "uploads/",
limits: {
fileSize: 5 * 1024 * 1024, // 5MB limit
},
});
Only accept certain file types:
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"));
}
},
});
To handle multiple file uploads:
export const configureFileUploadMiddleware: MiddlewareConfigFn = (config) => {
config.set("multer", upload.array("files", 10)); // Max 10 files
return config;
};
For more options, see the Multer documentation.