You are viewing the preview version of this book
Click here for the full version.

Downloads

Now that we have a good overview of what the example is app is about, let's see how the various focus points are implemented! In this chapter, we'll focus on file downloads, both for the (public) promo images and the file deliverables. The latter is the more critical one, as that involves access control: only users who bought the product should be able to download it.

Downloads

Promo images

Let's start with the easier of the two, the promo images!

When the client fetches the product item the backend returns the image URL as well:

paths:
  /product/{id}:
    get:
      summary: Get a product by id
      # ...
      responses:
        '200':
          description: The product
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Product'
components:
  schemas:
    Product:
      type: object
      properties:
        image:
          type: string
          description: Promo image URL
          example: /api/product/product1/image
        # ...

This points to a public endpoint, no authentication needed. Because of this, it can be used as an img src:

<img class="object-fit-contain" src=${product.image}/>

On the backend, there is a path for returning the image bytes for a product image:

paths:
  /product/{id}/image:
    get:
      security: []
      summary: Download the product image
      # ...
      responses:
        '200':
          description: successful operation
          content:
            'image/*':
              schema:
                type: string
                format: binary

Behind the API, the implementation reads the file from the filesystem and writes the contents to the response:

import stream from "node:stream/promises";

const product = await db.get(
  "SELECT * FROM Product WHERE id = :id",
  {":id": c.request.params.id}
);

res.status(200)
  .type(product.image_content_type)
  .set("Cache-Control", "no-cache");

await stream.pipeline(
  fs.createReadStream(path.join(
    __dirname, "images", product.image
  )),
  res,
)
The client downloading the promo image

Secure download

There is more, but you've reached the end of this preview
Read this and all other chapters in full and get lifetime access to:
  • all future updates
  • full web-based access
  • PDF and Epub versions