Is there any way to create an entry with media field in strapi?

Viewed 1120

I'm trying to create an entry in strapi, that contains field of type media.

Now I'm using code provided in documentation. But, in fact, it is creating an entry, and then adding file to it. So media field cant't be made required.

async create(data, { files } = {}) {
  const entry = await strapi.query(model).create(data);

  if (files) {
    await this.uploadFiles(entry, files, { model });
    return this.findOne({ id: entry.id });
  }

  return entry;
}

I would like to create an entry in single request. Is it possible?

1 Answers

There has to be two separate function calls to Strapi on the service file – one for creating the entry, one for uploading files & linking the files to an entry.


However, it is possible to solve your issue.

There are two particularly important Strapi concepts need to be understood here: controller and service.

Click through the links to read the official doc, but here is a quick overview.

  • Controller is what handles each API call.
  • Service is a set of utility functions. They are used to interact with the database (among other things).

There are default implementations for both of them, and default controller implementation calls corresponding default service implementation.

The one you showed is the default implementation for service. But it makes more sense to customize the controller in this case.


This is the default implementation of controller create:

const { parseMultipartData, sanitizeEntity } = require('strapi-utils');

module.exports = {
  /**
   * Create a record.
   *
   * @return {Object}
   */

  async create(ctx) {
    let entity;
    if (ctx.is('multipart')) {
      const { data, files } = parseMultipartData(ctx);
      // *** Notice here it is calling the service function ...
      entity = await strapi.services.restaurant.create(data, { files });
    } else {
      // *** ... or here.
      entity = await strapi.services.restaurant.create(ctx.request.body);
    }
    return sanitizeEntity(entity, { model: strapi.models.restaurant });
  },
};

To make the media field mandatory, override the default implementation to reject any request that does not have file(s). For example:

// ...

  async create(ctx) {
    ctx.assert(ctx.is('multipart'), 400, 'Hey! You need to add a file!');

    const { data, files } = parseMultipartData(ctx);
    let entity = await strapi.services.restaurant.create(data, { files });
    
    return sanitizeEntity(entity, { model: strapi.models.restaurant });
  }


// ...

Now any request that does not have files will receive 400, and no dangling data will be created.

Related