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.

ASP.NET Core hands you an uploaded file as an IFormFile parameter: IFormFile avatar gets the file from the form field avatar. A file has a .FileName, the name it had on the sender's computer, a .Length in bytes, and .OpenReadStream() to read its bytes. A route that reads form files asks for an anti-forgery check, which this shop doesn't run, so the route turns it off with DisableAntiforgery(). For example, a route that takes a customer's avatar:

var avatarRoute = app.MapPost("/customers/{id}/avatar", (int id, IFormFile avatar) => {
    return Results.Json(new { name = avatar.FileName }, statusCode: 201);
});
avatarRoute.DisableAntiforgery();

When the request has no such field, the parameter is null, and answering 400 is up to you. To keep the bytes, a table needs a BLOB column ("binary large object"): a byte[] value is saved as one. 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/{id}/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
Answer the size, data.Length, not the bytes themselves: the client already has them. Until the route's last return is written, C# stops with CS1643: not all code paths return a value.


STEP 1 OF 12
    Ctrl + Enter to check