Back to Wasp

File Uploads

web/versioned_docs/version-0.25/guides/integrations/file-upload.md

0.25.03.7 KB
Original Source

import LastCheckedWithVersionsNotice from "@site/src/components/LastCheckedWithVersionsNotice";

File Uploads

<LastCheckedWithVersionsNotice versions={{ Wasp: "0.24", multer: "2.1.1" }} />

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:

bash
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:

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)),
    // highlight-start
    apiNamespace("/api/upload", { middlewareConfigFn: configureFileUploadMiddleware }),
    api("POST", "/api/upload", uploadFile),
    // highlight-end
  ],
})

3. Create the API handlers

Create the middleware configuration and upload handler:

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:

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:

ts
const upload = multer({ dest: "my-custom-uploads/" });

Limit file size

Add file size limits:

ts
const upload = multer({
  dest: "uploads/",
  limits: {
    fileSize: 5 * 1024 * 1024, // 5MB limit
  },
});

Filter file types

Only accept certain file types:

ts
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:

ts
export const configureFileUploadMiddleware: MiddlewareConfigFn = (config) => {
  config.set("multer", upload.array("files", 10)); // Max 10 files
  return config;
};

For more options, see the Multer documentation.