---
slug: /references/file-provider-module
---
import { TypeList } from "docs-ui"
# 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`.
The 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`:
```ts title="src/modules/my-file/service.ts"
import { AbstractFileProviderService } from "@medusajs/framework/utils"
class MyFileProviderService extends AbstractFileProviderService {
// TODO implement methods
}
export 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
```ts
import { Logger } from "@medusajs/framework/types"
import { AbstractFileProviderService } from "@medusajs/framework/utils"
type InjectedDependencies = {
logger: Logger
}
type Options = {
apiKey: string
}
class MyFileProviderService extends AbstractFileProviderService {
protected logger_: Logger
protected options_: Options
static identifier = "my-file"
// assuming you're initializing a client
protected client
constructor (
{ logger }: InjectedDependencies,
options: Options
) {
super()
this.logger_ = logger
this.options_ = options
// assuming you're initializing a client
this.client = new Client(options)
}
}
export 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
```ts
class MyFileProviderService extends AbstractFileProviderService {
static identifier = "my-file"
// ...
}
```
### 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
```ts
class MyFileProviderService extends AbstractFileProviderService {
static validateOptions(options: Record) {
if (!options.apiKey) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
"API key is required in the provider's options."
)
}
}
}
```
#### Parameters
`","description":"The provider's options.","optional":false,"defaultValue":"","expandable":false,"children":[]}]} expandUrl="https://docs.medusajs.com/learn/fundamentals/data-models/manage-relationships#retrieve-records-of-relation" sectionTitle="validateOptions"/>
### upload
This method uploads a file using your provider's custom logic.
#### Example
```ts
class MyFileProviderService extends AbstractFileProviderService {
// ...
async upload(
file: ProviderUploadFileDTO
): Promise {
// TODO upload file to third-party provider
// or using custom logic
return {
url: "some-url.com",
key: "file-name"
}
}
}
```
#### Parameters
#### Returns
### delete
This method deletes the file from storage.
#### Example
```ts
class MyFileProviderService extends AbstractFileProviderService {
// ...
async delete(file: ProviderDeleteFileDTO): Promise {
// TODO logic to remove the file from storage
// Use the `file.fileKey` to delete the file
// for example:
this.client.delete(file.fileKey)
}
}
```
#### Parameters
#### Returns
### 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
```ts
class MyFileProviderService extends AbstractFileProviderService {
// ...
async getPresignedDownloadUrl(
fileData: ProviderGetFileDTO
): Promise {
// TODO logic to get the presigned URL
// Use the `file.fileKey` to delete the file
// for example:
return this.client.getPresignedUrl(fileData.fileKey)
}
}
```
#### Parameters
#### Returns
---
## 3. Create Module Definition File
Create the file `src/modules/my-file/index.ts` with the following content:
```ts title="src/modules/my-file/index.ts"
import MyFileProviderService from "./service"
import {
ModuleProvider,
Modules
} from "@medusajs/framework/utils"
export default ModuleProvider(Modules.FILE, {
services: [MyFileProviderService],
})
```
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`:
The File Module accepts one provider only.
```ts title="medusa-config.ts"
module.exports = defineConfig({
// ...
modules: [
{
resolve: "@medusajs/medusa/file",
options: {
providers: [
// default provider
{
resolve: "@medusajs/medusa/file-local",
id: "local",
},
{
// if module provider is in a plugin, use `plugin-name/providers/my-file`
resolve: "./src/modules/my-file",
id: "my-file",
options: {
// provider options...
},
},
],
},
},
]
})
```
---
## 5. Test it Out
To test out your file provider, use the Medusa Admin or the [Upload API route](https://docs.medusajs.com/v2/api/admin#uploads_postuploads) to upload a file.