or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

base-service.mdfile-service.mdfulfillment-service.mdindex.mdnotification-service.mdoauth-service.mdpayment-service.mdsearch-service.md

file-service.mddocs/

0

# File Service

1

2

Interface for file storage service implementations providing upload and delete operations for handling file assets across different storage providers.

3

4

**Deprecation Notice**: Use `AbstractFileService` from @medusajs/medusa instead.

5

6

## Capabilities

7

8

### Static Methods

9

10

Type checking and identification methods for file services.

11

12

```javascript { .api }

13

/**

14

* Static property identifying this as a file service

15

*/

16

static _isFileService: boolean;

17

18

/**

19

* Checks if an object is a file service

20

* @param {object} obj - Object to check

21

* @returns {boolean} True if obj is a file service

22

*/

23

static isFileService(obj: object): boolean;

24

```

25

26

### Core File Operations

27

28

Abstract methods that must be implemented by child classes for file storage operations.

29

30

```javascript { .api }

31

/**

32

* Uploads files to the storage provider

33

* @returns {any} Upload result

34

* @throws {Error} If not overridden by child class

35

*/

36

upload(): any;

37

38

/**

39

* Deletes files from the storage provider

40

* @returns {any} Deletion result

41

* @throws {Error} If not overridden by child class

42

*/

43

delete(): any;

44

```

45

46

## Implementation Example

47

48

```javascript

49

import { FileService } from "medusa-interfaces";

50

import fs from "fs";

51

import path from "path";

52

53

class LocalFileService extends FileService {

54

constructor(options) {

55

super();

56

this.uploadDir = options.upload_dir || "./uploads";

57

this.baseUrl = options.base_url || "http://localhost:9000";

58

}

59

60

async upload(files) {

61

const uploadedFiles = [];

62

63

// Handle single file or array of files

64

const fileArray = Array.isArray(files) ? files : [files];

65

66

for (const file of fileArray) {

67

// Generate unique filename

68

const filename = `${Date.now()}-${file.originalname}`;

69

const filepath = path.join(this.uploadDir, filename);

70

71

// Ensure upload directory exists

72

if (!fs.existsSync(this.uploadDir)) {

73

fs.mkdirSync(this.uploadDir, { recursive: true });

74

}

75

76

// Write file to disk

77

fs.writeFileSync(filepath, file.buffer);

78

79

uploadedFiles.push({

80

url: `${this.baseUrl}/uploads/${filename}`,

81

key: filename,

82

originalname: file.originalname,

83

size: file.size,

84

mimetype: file.mimetype

85

});

86

}

87

88

return uploadedFiles.length === 1 ? uploadedFiles[0] : uploadedFiles;

89

}

90

91

async delete(fileKey) {

92

try {

93

const filepath = path.join(this.uploadDir, fileKey);

94

95

if (fs.existsSync(filepath)) {

96

fs.unlinkSync(filepath);

97

return { success: true, key: fileKey };

98

} else {

99

throw new Error(`File not found: ${fileKey}`);

100

}

101

} catch (error) {

102

throw new Error(`Failed to delete file: ${error.message}`);

103

}

104

}

105

}

106

107

// AWS S3 implementation example

108

class S3FileService extends FileService {

109

constructor(options) {

110

super();

111

this.s3Client = new AWS.S3({

112

accessKeyId: options.access_key_id,

113

secretAccessKey: options.secret_access_key,

114

region: options.region

115

});

116

this.bucket = options.bucket;

117

}

118

119

async upload(files) {

120

const uploadedFiles = [];

121

const fileArray = Array.isArray(files) ? files : [files];

122

123

for (const file of fileArray) {

124

const key = `${Date.now()}-${file.originalname}`;

125

126

const uploadParams = {

127

Bucket: this.bucket,

128

Key: key,

129

Body: file.buffer,

130

ContentType: file.mimetype,

131

ACL: 'public-read'

132

};

133

134

const result = await this.s3Client.upload(uploadParams).promise();

135

136

uploadedFiles.push({

137

url: result.Location,

138

key: result.Key,

139

originalname: file.originalname,

140

size: file.size,

141

mimetype: file.mimetype

142

});

143

}

144

145

return uploadedFiles.length === 1 ? uploadedFiles[0] : uploadedFiles;

146

}

147

148

async delete(fileKey) {

149

try {

150

const deleteParams = {

151

Bucket: this.bucket,

152

Key: fileKey

153

};

154

155

await this.s3Client.deleteObject(deleteParams).promise();

156

return { success: true, key: fileKey };

157

} catch (error) {

158

throw new Error(`Failed to delete file from S3: ${error.message}`);

159

}

160

}

161

}

162

```

163

164

## Usage in Medusa

165

166

File services are typically used in Medusa for:

167

168

- **Product Images**: Uploading and managing product photos

169

- **User Avatars**: Profile picture management

170

- **Document Storage**: Invoices, receipts, and other documents

171

- **Media Assets**: General file asset management

172

173

**Basic Usage Pattern:**

174

175

```javascript

176

// In a Medusa service or API route

177

class ProductService {

178

constructor({ fileService }) {

179

this.fileService_ = fileService;

180

}

181

182

async uploadProductImages(productId, imageFiles) {

183

// Upload images using the file service

184

const uploadedImages = await this.fileService_.upload(imageFiles);

185

186

// Store image URLs in product record

187

await this.updateProduct(productId, {

188

images: uploadedImages.map(img => img.url)

189

});

190

191

return uploadedImages;

192

}

193

194

async deleteProductImage(imageKey) {

195

// Delete image file

196

await this.fileService_.delete(imageKey);

197

198

// Remove from product record

199

// ... update logic

200

}

201

}

202

```

203

204

## Error Handling

205

206

Both abstract methods throw descriptive errors when not implemented:

207

208

- `"upload must be overridden by the child class"`

209

- `"delete must be overridden by the child class"`

210

211

## Common Implementation Patterns

212

213

### File Upload Parameters

214

215

Most implementations expect file objects with these properties:

216

217

```javascript

218

{

219

originalname: string, // Original filename

220

buffer: Buffer, // File data

221

mimetype: string, // MIME type

222

size: number // File size in bytes

223

}

224

```

225

226

### Return Value Patterns

227

228

Upload operations typically return:

229

230

```javascript

231

{

232

url: string, // Public URL to access the file

233

key: string, // Storage identifier/key

234

originalname: string, // Original filename

235

size: number, // File size

236

mimetype: string // MIME type

237

}

238

```

239

240

Delete operations typically return:

241

242

```javascript

243

{

244

success: boolean, // Operation success status

245

key: string // Key of deleted file

246

}

247

```