Skip to content

File Uploads ​

Define File Columns ​

Use the file() utility within your entity definition to mark a column as a file field. This enables multipart middleware support for the entity.

js
import { defineEntity, file, primaryId, timestamps } from "@codingkiwi/baseline/database/utils.js";
import { mysqlTable, varchar } from "drizzle-orm/mysql-core";

export const userProfile = defineEntity({
    table: mysqlTable("user_profile", {
        id: primaryId(),
        username: varchar({ length: 50 }).notNull(),
        // The file column
        avatar: file(),
        ...timestamps,
    })
});

INFO

If a file column is non-nullable, all POST and PUT requests to that entity must use multipart/form-data. If you are uploading a file, you must use multipart/form-data regardless of whether the column is nullable. If all file columns are nullable and you are only updating non-file fields, you can use standard application/json.

Configure File Constraints ​

Pass configuration options to the file() function to enforce restrictions. Use maxSize to limit the upload size in bytes.

js
// Limit upload to 5MB
file({
    maxSize: 5 * 1024 * 1024,
}),

WARNING

The framework uses the largest maxSize defined among all file columns to deny uploads during the initial upload phase. If no maxSize is specified for a file column, it defaults to 1MB. Individual maxSize constraints are verified only after all files have been uploaded due to technical reasons. If an upload exceeds the limit, the server returns a 413 Payload Too Large error.

Structure Multipart Requests ​

Use multipart/form-data to send both structured JSON data and binary files in a single request. Include a data field for all non-file entity fields.

Request Body Table ​

Field KeyTypeDescription
datastring (JSON)A JSON-stringified object containing all non-file entity fields.
[column_name]fileThe binary file matching the entity's file column name.

Example Payload:

If you are uploading a userProfile with a username and an avatar, your multipart/form-data body should look like this:

  • data: {"username": "coding_wizard"}
  • avatar: [Binary File Data]

DANGER

If the data field is missing or contains invalid JSON, the request will fail with a 400 Bad Request error.

Use the Baseline Client ​

The baseline-client automatically detects File instances in your data and transforms the payload into the required multipart/form-data format. You do not need to manually construct FormData or nest JSON fields.

js
// The client handles all multipart complexity automatically
await baseline.api.create("users", {
    username: "coding_wizard",
    avatar: fileInstance // An instance of File
});

Access Uploaded Files ​

Access uploaded files through the built-in /files route using the filename stored in your database.

Example:

If the avatar column contains profile_image_abc123.jpg, access it at: http://localhost:3000/files/profile_image_abc123.jpg

If a file is not found, the endpoint returns a 404 Not Found error:

json
{
  "error": "Not Found"
}