Start learning free

LESSON 116 OF 173 · BACKEND: PAYMENTS AND OTHER SERVICES

Upload a Photo

Practice

A photo is not text but bytes: numbers from 0 to 255 that only an image viewer makes sense of. A browser doesn't send a file as JSON but as multipart/form-data: the body is cut into parts, one per form field, and a file's part carries its file name and its bytes.

Express doesn't read such a body by itself; the package multer does. With upload.single("avatar") between the path and the function, multer reads the one file sent in the field avatar and puts it in req.file. That object has .originalname, the name the file had on the sender's computer, and .buffer, its bytes, in a Buffer (Node's type for bytes). Its type comes with multer, so TypeScript knows these properties. For example, a route that takes a customer's avatar:

app.post("/customers/:customerId/avatar", upload.single("avatar"), (req: Request, res: Response) => {
  const avatar = req.file;
  res.status(201).json({ name: avatar.originalname });
});

When the request has no such file, req.file is undefined, so the route checks for that first and answers 400 Bad Request. To keep the bytes, a table needs a BLOB column ("binary large object"). With product_id as the primary key, each product has one photo, and INSERT OR REPLACE lets a new photo take the old one's place instead of failing.

The tests send files in the field photo (each character of these files is one byte) and look in the table with GET /check/photos:

POST /products/1/photo  (photo: mug.png, "a photo of a mug")  →  201  {"filename": "mug.png", "product_id": 1, "size": 16}
POST /products/3/photo  (photo: lamp.jpg, "a photo of a lamp")  →  201  {"filename": "lamp.jpg", "product_id": 3, "size": 17}
POST /products/1/photo  (photo: mug-new.png, "a better photo of the mug")  →  201  {"filename": "mug-new.png", "product_id": 1, "size": 25}
POST /products/1/photo  (form name=Mug, no file)  →  400  {"error": "No photo in the request"}
GET /check/photos  →  200  [{"filename": "mug-new.png", "product_id": 1, "size": 25}, {"filename": "lamp.jpg", "product_id": 3, "size": 17}]

Your task: create a photos table, then add POST /products/:productId/photo: take the file from the field photo, answer 400 when there is none, store its name and bytes for the product (a new photo replaces the old one), and answer 201 with the product id, the file name and the size in bytes.


Assignment
Follow the Coding Tutorial to create the photos table and the upload route.


Hint
multer is already imported, and upload is made from it. Type the route's req and res like the other routes'. Answer the size, data.length, not the bytes themselves: the client already has them.


STEP 1 OF 9
    Ctrl + Enter to check