code4romania / teacher-workout-backend

Teacher Workout backend (API for mobile apps & for the web client)
Mozilla Public License 2.0
7 stars 34 forks source link

Add support for uploading an image #57

Closed pirvudoru closed 7 months ago

pirvudoru commented 2 years ago

We need to support file upload via https://github.com/jaydenseric/graphql-multipart-request-spec#server to allow clients easy integration.

As it looks, we should be able to use https://github.com/JannikLassahn/graphql-dotnet-upload

If not, what can we do?

  scalar Upload

  type File {
    filename: String!
    mimetype: String!
    encoding: String!
  }

  type Mutation {
    singleUpload(file: Upload!): File!
  }
nicolaes commented 7 months ago

I created a new table to store image blobs, using the mentioned upload lib.

In order to get the images, I'm thinking we should create a HTTP GET based on the image id - and populate the URLs in Images table. E.g. GET /image/f1a019c8-9f52-4a70-919d-d6ccf9fc3d5a which responds with the stored content type header.

nicolaes commented 7 months ago

UI admin for images is "choose file or drop image here", so end-to-end upload flow can be:

  1. Upload individual images with singleUpload mutation when they are dropped in the screen singleUpload(file: $file) { fileBlobId }
  2. When upload is done, show the image from server: <img src="/image/42">
  3. Include the ID when submitting the form: themeCreate(input: { title: "My Theme", fileBlobId: "42"})
  4. Backend creates a new thumbnail linked to fileBlobId: 42, then persists the actual theme

Next steps for backend:

  1. Delete images without a parent to clean up space (e.g. with a Hangfire nightly job)
  2. (optional) Deliver the most recent few images based on CreatedAt, to allow UI to select from existing files Screenshot 2023-11-30 at 17 00 47
nicolaes commented 7 months ago

Added new features:

1. singleUpload mutation

New mutation allowing an image upload (stored in the database). Response returns the upload ID that you can reference later. See #83 for tests and API call.

2. Get uploaded image

New endpoint can be used via HTTP GET to retrieve files: <img src="/file/{fileBlobId}" />. More details in #84.

3. themeCreate query

Themes can now be created with a fileBlobId reference. See #84 for API call.

4. Get recent uploads

A new query recentImageUploads allows getting latest uploaded images. If integrated in UI, this should result in less orphan images and easier catchup if you refresh the page. API call in #84.

5. Orphan upload cleanup

Uploads that are not referenced in Images table should be deleted via a nightly cronjob. See tests in #84.

Not covered