Strapi Media Upload — Admin Upload, Allowed Types, and Size Limits
In this tutorial, you will learn how to handle media uploads in Strapi — from uploading images through the admin panel and API, to configuring allowed file types, size limits, and organizing files in the Media Library.
What You'll Learn
- How to upload files through the admin panel Media Library
- How to upload files programmatically through the API
- How to configure allowed file types and size limits
- How to organize files with folders
- How files are stored and referenced in content entries
- How to handle file validation errors
Why It Matters
Media files are central to most content management systems. Articles need images, products need photos, user profiles need avatars. Understanding how Strapi handles uploads ensures your media is stored securely, organized logically, and accessible through the API in a predictable way.
Real-World Use
A recipe site stores thousands of food photos. Authors upload images through a form in the frontend. The images are validated (JPEG/PNG only, max 5MB), stored in folders organized by recipe ID, and automatically referenced in the recipe content entry. The frontend displays the images using Strapi's API URLs.
Learning Path
flowchart LR A["Advanced Auth"] --> B["Media Upload
-- You are here"]:::current B --> C["Upload Providers"] C --> D["Image Optimization"] D --> E["File Management"] classDef current fill:#4945ff,color:#fff,stroke-width:2px
Admin Panel Upload
The Media Library in the admin panel provides a user-friendly interface for uploading files.
Media Library
-- Upload button
-- Select files from computer
-- Or drag and drop files
-- Files appear in the grid after upload
-- Click a file to view details and edit metadata
To upload from the admin panel:
- Go to Media Library in the left sidebar
- Click the "Upload" button
- Select files from your computer or drag them into the upload area
- Files are uploaded and appear in the grid
After uploading, you can:
- View file details (name, URL, dimensions, size, MIME type)
- Edit the file name and alternative text
- Replace the file with a new version
- Move the file to a folder
- Copy the file URL for use in content
API Upload
Upload files programmatically through the upload API:
// POST /api/upload
// Content-Type: multipart/form-data
// Body: FormData with file(s)
// Frontend upload example:
async function uploadImage(file) {
const jwt = localStorage.getItem("strapi_jwt");
const formData = new FormData();
formData.append("files", file);
const response = await fetch("http://localhost:1337/api/upload", {
method: "POST",
headers: {
Authorization: `Bearer ${jwt}`,
},
body: formData,
});
const uploadedFiles = await response.json();
// Returns array of uploaded file objects
return uploadedFiles;
}
// Response:
[
{
"id": 1,
"name": "pizza.jpg",
"alternativeText": null,
"caption": null,
"width": 1920,
"height": 1080,
"formats": {
"thumbnail": { "url": "/uploads/thumbnail_pizza.jpg", ... },
"small": { "url": "/uploads/small_pizza.jpg", ... },
"medium": { "url": "/uploads/medium_pizza.jpg", ... }
},
"hash": "pizza_c4d3f2b1e5",
"ext": ".jpg",
"mime": "image/jpeg",
"size": 2048576,
"url": "/uploads/pizza_c4d3f2b1e5.jpg",
"provider": "local"
}
]
The upload response includes the file's ID, which you can use to associate the file with a content entry.
Associating Files with Content
Media fields on content types store a reference to uploaded files. You can upload a file and immediately associate it with a content entry.
// Upload and assign to an article in one request:
// POST /api/upload
// FormData:
// files: [the image file]
// data: JSON.stringify({
// ref: "api::article.article",
// refId: 1,
// field: "cover_image"
// })
// Or upload first, then associate:
// Step 1: Upload file, get file ID
const [uploadedFile] = await uploadImage(file);
const fileId = uploadedFile.id;
// Step 2: Update the article with the file ID
await fetch("http://localhost:1337/api/articles/1", {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${jwt}`,
},
body: JSON.stringify({
data: {
cover_image: fileId,
},
}),
});
Configuring Allowed Types
Restrict which file types users can upload:
// config/plugins.js
module.exports = {
upload: {
config: {
sizeLimit: 5 * 1024 * 1024, // 5MB in bytes
breakpoints: {
large: 1000,
medium: 750,
small: 500,
},
},
},
};
For more granular control, configure allowed MIME types:
// src/extensions/upload/config.js
module.exports = {
// Only allow images and PDFs
allowedTypes: ["image/jpeg", "image/png", "image/webp", "application/pdf"],
// Or use categories
allowedTypes: ["images", "files"], // videos and audios excluded
};
The MIME type restriction applies to both admin panel and API uploads. Invalid file types return a 400 error.
Size Limits
Control upload size limits at multiple levels:
// 1. Strapi upload plugin configuration
// config/plugins.js
module.exports = {
upload: {
config: {
sizeLimit: 10 * 1024 * 1024, // 10MB
},
},
};
// 2. Server-level limit (Koa body parser)
// config/middlewares.js
{
name: "strapi::body",
config: {
multipart: true,
includeUnparsed: true,
formLimit: "56kb",
jsonLimit: "1mb",
textLimit: "1mb",
formidable: {
maxFileSize: 10 * 1024 * 1024, // 10MB
},
},
}
// 3. Reverse proxy level (nginx, Cloudflare)
// nginx config:
// client_max_body_size 10M;
The most restrictive limit wins. If Strapi allows 10MB but nginx allows 5MB, uploads over 5MB are rejected by nginx.
File Validation
Strapi validates uploaded files against the content type's field configuration:
// Media field configuration in Content-Type Builder
{
"type": "media",
"allowedTypes": ["images"], // Only images allowed
"multiple": false // Single file, not gallery
}
// Multiple: true — allows multiple files
// Multiple: false — allows one file per field
// allowedTypes options:
// "images" — JPEG, PNG, WebP, GIF, SVG, AVIF
// "files" — PDF, DOC, XLS, ZIP, TXT
// "videos" — MP4, MOV, AVI, WebM
// "audios" — MP3, WAV, OGG, AAC
Folder Organization
Organize files with folders in the Media Library:
// Create folders via admin panel:
// Media Library > Add New Folder
// Structure:
// /images
// /articles
// /authors
// /categories
// /documents
// /videos
// Upload directly to a folder via API:
const formData = new FormData();
formData.append("files", file);
formData.append("folder", 5); // Folder ID
await fetch("http://localhost:1337/api/upload", {
method: "POST",
headers: { Authorization: `Bearer ${jwt}` },
body: formData,
});
Organizing files in folders from the start prevents the Media Library from becoming an unmanageable mess as you accumulate thousands of files.
Common Mistakes
Uploading files without size limits. Without size limits, users can upload multi-GB files that exhaust server disk space and cause upload timeouts. Always set reasonable size limits.
Not validating file types on the client side. Server-side validation is essential, but client-side validation improves user experience. Validate file types and sizes before sending the upload request.
Using local storage in production without backup. Strapi's default local upload provider stores files on the server's filesystem. If the server is replaced or the disk fails, all uploads are lost. Use cloud storage providers in production.
Uploading files without associating them with content. Uploaded files that are not linked to any content entry become orphaned. They take up storage space but are never displayed.
Not setting alternative text on images. Accessibility requires alt text on images. Make alternative text a required field in your media field configuration.
Practice Questions
What is the API endpoint for uploading a file to Strapi? Answer:
POST /api/uploadwithContent-Type: multipart/form-dataand the file in thefilesfield of the FormData.How do you restrict uploads to only image files? Answer: In the Content-Type Builder, set the media field's
allowedTypesto["images"]. You can also configure the upload plugin to restrict by MIME types.What happens if you upload a file larger than the configured size limit? Answer: Strapi returns a 400 error with a message indicating the file exceeds the maximum allowed size. The file is not saved.
Challenge: Build a complete image upload system: (1) Configure Strapi with a 10MB size limit and image-only MIME types, (2) Create a frontend upload form with drag-and-drop that validates file type and size before uploading, (3) Upload the file and associate it with a specific content entry, (4) Display the uploaded image on a page, (5) Implement folder organization: upload article images to
/images/articlesand author images to/images/authors.
FAQ
Mini Project
Your task: Build a complete media management workflow.
- Configure upload settings: 5MB max size, allow images only (JPEG, PNG, WebP).
- Create folder structure in the Media Library:
images/products/,images/blog/,documents/. - Create a content type "Product" with fields: name, description, price, and a media field "photos" (multiple images allowed).
- Write a frontend upload form that:
- Validates file type and size before uploading
- Uploads files to the API
- Associates uploaded files with a new product
- Displays the uploaded images
- Test with valid files (should succeed) and invalid files (wrong type, too large — should fail with clear error messages).
What's Next
Now that you understand media upload, proceed to Upload Providers to learn how to configure cloud storage with Amazon S3, Cloudinary, and Cloudflare R2 instead of the default local filesystem storage. After that, explore Image Optimization for responsive images and compression.
Related lessons:
- Node.js File Upload — How file upload works
- REST API — Upload endpoints and responses
- WordPress Media Library — Compare with Strapi media
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro