Episode 3 — NodeJS MongoDB Backend Architecture / 3.7 — Handling Files with Express
3.7 — Exercise Questions: Handling Files with Express
Practice questions for all six subtopics in Section 3.7. Mix of conceptual, coding, and hands-on exercises. Try each without reopening the lesson files first.
How to use this material (instructions)
- Read lessons in order --
README.md, then3.7.athrough3.7.f. - Answer closed-book first -- write an answer, then compare to the lesson.
- Code exercises -- build working Express snippets for every coding question.
- Redo misses -- retry wrong questions after sleep (spaced repetition).
- Interview prep -- pair with
3.7-Interview-Questions.md.
3.7.a -- Understanding Multer (Q1-Q7)
Q1. Why can express.json() and express.urlencoded() not handle file uploads? What Content-Type do they expect?
Q2. What HTML attribute must be set on a <form> to enable file uploads? What happens if you forget it?
Q3. What is multipart/form-data? Describe how the browser splits the request body into parts.
Q4. List the four Multer upload methods (single, array, fields, none). For each, state what req.file and req.files contain.
Q5. Why should Multer be applied as route-level middleware, not globally with app.use()?
Q6. What is the difference between using { dest: 'uploads/' } and providing a full diskStorage configuration?
Q7. Coding exercise: Write a minimal Express + Multer setup that accepts a single file upload on POST /upload and returns the file info as JSON.
3.7.b -- File Upload with Multer (Q8-Q13)
Q8. Write Express code that accepts up to 5 photos on a field named gallery and returns an array of filenames.
Q9. How do you upload files from different form fields in the same request (e.g., avatar and coverPhoto)? Write the Multer configuration.
Q10. What is upload.none() and when would you use it?
Q11. After a successful single upload, list at least 6 properties available on req.file.
Q12. Coding exercise: Build a form (HTML or Postman) that sends a username (text) and an avatar (file). Write the Express route that saves the file and responds with both req.body.username and req.file.filename.
Q13. What error does Multer throw if you send a file to a field name that does not match the one in upload.single('fieldName')? How do you catch it?
3.7.c -- Storage Engines (Q14-Q20)
Q14. Explain the difference between multer.diskStorage() and multer.memoryStorage(). When would you pick each?
Q15. In diskStorage, what are the two callback functions you must define? What arguments does each receive?
Q16. Write a diskStorage configuration that:
- Saves files to
uploads/images/ - Names each file as
<timestamp>-<originalname>
Q17. When using memoryStorage, where does the file data live? What property on req.file holds it?
Q18. Why is memory storage risky for large files? What could happen if 100 users upload 50 MB files simultaneously?
Q19. Coding exercise: Create a custom storage engine (implementing _handleFile and _removeFile) that logs every upload to the console before saving to disk.
Q20. What happens to the file stored on disk if your route handler throws an error after Multer has already saved the file? How would you clean up?
3.7.d -- File Validation and Security (Q21-Q27)
Q21. Write a fileFilter function that accepts only JPEG, PNG, and WebP images based on MIME type.
Q22. Why is checking file.mimetype alone insufficient for security? What can an attacker do?
Q23. What are magic bytes (file signatures)? Give the magic bytes for JPEG, PNG, and PDF.
Q24. Write code that validates a file's magic bytes using the file-type package after a memory-storage upload.
Q25. List at least 5 items from a file-upload security checklist (e.g., size limits, filename sanitization, storage location).
Q26. Why should uploaded files be stored outside the web root? What attack does this prevent?
Q27. Coding exercise: Build a secure upload endpoint that:
- Limits file size to 2 MB
- Accepts only PNG and JPEG via fileFilter
- Validates magic bytes after upload
- Sanitizes the filename (removes special characters)
- Returns a 400 error with a clear message if any check fails
3.7.e -- Working with Express Static (Q28-Q31)
Q28. What does express.static() do? Why should it be placed before route definitions?
Q29. If your static middleware is app.use(express.static('public')) and there is a file at public/images/logo.png, what URL serves it?
Q30. What is a virtual path prefix? Write middleware that serves the public/ folder under the /static URL prefix.
Q31. Why should you use absolute paths (/css/style.css) rather than relative paths (css/style.css) in HTML templates that reference static files?
3.7.f -- Cloud Storage: Cloudinary and ImageKit (Q32-Q40)
Q32. Give at least 4 reasons why production applications use cloud storage instead of saving files to the server's local disk.
Q33. Describe the production upload pipeline from client to database in order.
Q34. Write the Cloudinary configuration block using environment variables.
Q35. What is cloudinary.uploader.upload_stream() and why is it used with memory storage?
Q36. Write a helper function that takes a Buffer and uploads it to Cloudinary, returning the secure_url and public_id.
Q37. What does the multer-storage-cloudinary package do? How does it differ from the manual buffer approach?
Q38. List at least 4 Cloudinary URL-based transformation parameters (e.g., w_200).
Q39. How do you delete a file from Cloudinary? What identifier do you need?
Q40. Coding exercise: Build a complete avatar upload system:
PUT /api/users/:id/avatar— accepts an image, uploads to Cloudinary, saves the URL in an in-memory user objectDELETE /api/users/:id/avatar— deletes the image from Cloudinary, removes the URL- Include file validation (type + size) and error handling
Cross-Topic Challenges (Q41-Q45)
Q41. Compare Multer disk storage, memory storage, and multer-storage-cloudinary in a table with at least 5 criteria (speed, disk usage, cloud dependency, cleanup, use case).
Q42. A user reports: "I uploaded a profile picture but I see a broken image on the page." List 5 possible causes and how to debug each.
Q43. Design a file upload system for a social media app that supports profile pictures, post images (up to 10 per post), and video uploads (up to 100 MB). Describe your storage strategy, validation rules, and architecture.
Q44. You discover that someone uploaded a .php file disguised as a .jpg to your Express server. Walk through how the attack works and what layers of defense would have stopped it.
Q45. Full coding project: Build a photo gallery API with:
POST /api/photos— upload 1-5 images (Cloudinary), store URLs in an arrayGET /api/photos— list all photos with paginationDELETE /api/photos/:id— delete from Cloudinary and the array- File validation (images only, max 5 MB each)
- Error handling with appropriate status codes
Answer Hints (Short)
| Q | Hint |
|---|---|
| Q1 | express.json() handles application/json; files require multipart/form-data |
| Q4 | single -> req.file; array/fields/any -> req.files; none -> neither |
| Q6 | dest gives random filenames with no extension; diskStorage gives full control |
| Q13 | LIMIT_UNEXPECTED_FILE error; catch with error-handling middleware |
| Q14 | Disk writes to filesystem; memory holds Buffer in RAM |
| Q17 | req.file.buffer — a Node.js Buffer object |
| Q22 | Attackers can spoof MIME types; validate magic bytes instead |
| Q23 | JPEG: FF D8 FF; PNG: 89 50 4E 47; PDF: 25 50 44 46 |
| Q26 | Prevents direct execution of uploaded scripts via URL |
| Q33 | Client -> Multer (memory) -> Validate -> Cloud upload -> Save URL to DB -> Return URL |
| Q35 | Streams a Buffer to Cloudinary without touching disk |
| Q39 | cloudinary.uploader.destroy(publicId) — needs the public_id from the upload result |
<- Back to 3.7 -- Handling Files with Express (README)