How to Create a File Provider Module

In this document, you’ll learn how to create a file provider module and the methods you must implement in its main service.


Create Module Provider Directory#

Start by creating a new directory for your module provider.

If you're creating the module provider in a Medusa application, create it under the src/modules directory. For example, src/modules/my-file.

If you're creating the module provider in a plugin, create it under the src/providers directory. For example, src/providers/my-file.

NoteThe rest of this guide always uses the src/modules/my-file directory as an example.

2. Create the File Provider Service#

Create the file src/modules/my-file/service.ts that holds the implementation of the module's main service. It must extend the AbstractFileProviderService class imported from @medusajs/framework/utils:

src/modules/my-file/service.ts
1import { AbstractFileProviderService } from "@medusajs/framework/utils"2
3class MyFileProviderService extends AbstractFileProviderService {4  // TODO implement methods5}6
7export default MyFileProviderService

constructor#

The constructor allows you to access resources from the module's container using the first parameter, and the module's options using the second parameter.

If you're creating a client or establishing a connection with a third-party service, do it in the constructor.

Example

Code
1import { Logger } from "@medusajs/framework/types"2import { AbstractFileProviderService } from "@medusajs/framework/utils"3
4type InjectedDependencies = {5  logger: Logger6}7
8type Options = {9  apiKey: string10}11
12class MyFileProviderService extends AbstractFileProviderService {13  protected logger_: Logger14  protected options_: Options15  static identifier = "my-file"16  // assuming you're initializing a client17  protected client18
19  constructor (20    { logger }: InjectedDependencies,21    options: Options22  ) {23    super()24
25    this.logger_ = logger26    this.options_ = options27
28    // assuming you're initializing a client29    this.client = new Client(options)30  }31}32
33export default MyFileProviderService

identifier#

Each file provider has a unique ID used to identify it. The provider's ID will be stored as fs_{identifier}_{id}, where {id} is the provider's id property in the medusa-config.ts.

Example

Code
1class MyFileProviderService extends AbstractFileProviderService {2  static identifier = "my-file"3  // ...4}

validateOptions#

This method validates the options of the provider set in medusa-config.ts. Implementing this method is optional. It's useful if your provider requires custom validation.

If the options aren't valid, throw an error.

Example

Code
1class MyFileProviderService extends AbstractFileProviderService {2  static validateOptions(options: Record<any, any>) {3    if (!options.apiKey) {4      throw new MedusaError(5        MedusaError.Types.INVALID_DATA,6        "API key is required in the provider's options."7      )8    }9  }10}

Parameters

optionsRecord<any, any>
The provider's options.

upload#

This method uploads a file using your provider's custom logic. In this method, you can upload the file into your provider's storage, and return the uploaded file's details.

This method will be used when uploading product images, CSV files for imports, or other custom file uploads.

Example

Code
1class MyFileProviderService extends AbstractFileProviderService {2  // ...3  async upload(4    file: ProviderUploadFileDTO5  ): Promise<ProviderFileResultDTO> {6    // TODO upload file to third-party provider7    // or using custom logic8    // for example:9    this.client.upload(file)10
11    return {12      url: "some-url.com",13      key: "file-name-or-id"14    }15  }16}

Parameters

The file to upload.

Returns

PromisePromise<ProviderFileResultDTO>
The uploaded file's details.

delete#

This method deletes the file from storage. It's used when an admin user deletes a product image, or other custom file deletions.

Example

Code
1class MyFileProviderService extends AbstractFileProviderService {2  // ...3  async delete(file: ProviderDeleteFileDTO): Promise<void> {4    // TODO logic to remove the file from storage5    // Use the `file.fileKey` to delete the file6    // for example:7    this.client.delete(file.fileKey)8  }9}

Parameters

The details of the file to delete.

Returns

PromisePromise<void>
Resolves when the file is deleted.

getPresignedDownloadUrl#

This method is used to retrieve a download URL of the file. For some providers, such as S3, a presigned URL indicates a temporary URL to get access to a file.

If your provider doesn’t perform or offer a similar functionality, you can return the URL to download the file.

Example

Code
1class MyFileProviderService extends AbstractFileProviderService {2  // ...3  async getPresignedDownloadUrl(4    fileData: ProviderGetFileDTO5  ): Promise<string> {6    // TODO logic to get the presigned URL7    // Use the `file.fileKey` to delete the file8    // for example:9    return this.client.getPresignedUrl(fileData.fileKey)10  }11}

Parameters

The details of the file to get its presigned URL.

Returns

PromisePromise<string>
The file's presigned URL.

3. Create Module Definition File#

Create the file src/modules/my-file/index.ts with the following content:

src/modules/my-file/index.ts
1import MyFileProviderService from "./service"2import { 3  ModuleProvider, 4  Modules5} from "@medusajs/framework/utils"6
7export default ModuleProvider(Modules.FILE, {8  services: [MyFileProviderService],9})

This exports the module's definition, indicating that the MyFileProviderService is the module's service.


4. Use Module#

To use your File Module Provider, add it to the providers array of the File Module in medusa-config.ts:

NoteThe File Module accepts one provider only.
medusa-config.ts
1module.exports = defineConfig({2  // ...3  modules: [4    {5      resolve: "@medusajs/medusa/file",6      options: {7        providers: [8          // default provider9          {10            resolve: "@medusajs/medusa/file-local",11            id: "local",12          },13          {14            // if module provider is in a plugin, use `plugin-name/providers/my-file`15            resolve: "./src/modules/my-file",16            id: "my-file",17            options: {18              // provider options...19            },20          },21        ],22      },23    },24  ]25})

5. Test it Out#

To test out your file provider, use the Medusa Admin or the Upload API route to upload a file.

Was this page helpful?
Ask Anything
FAQ
What is Medusa?
How can I create a module?
How can I create a data model?
How do I create a workflow?
How can I extend a data model in the Product Module?
Recipes
How do I build a marketplace with Medusa?
How do I build digital products with Medusa?
How do I build subscription-based purchases with Medusa?
What other recipes are available in the Medusa documentation?
Chat is cleared on refresh
Line break