multermate 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/dist/cjs/index.js +38 -7
- package/dist/esm/index.js +38 -7
- package/dist/esm/package.json +1 -1
- package/index.d.ts +6 -6
- package/index.js +9 -9
- package/index.mjs +6 -6
- package/package.json +73 -73
- package/readme.md +524 -496
- package/types/index.d.ts +2 -0
package/readme.md
CHANGED
|
@@ -1,496 +1,524 @@
|
|
|
1
|
-
# Multer Mate
|
|
2
|
-
|
|
3
|
-
A robust and flexible file upload utility built on top of Multer, providing advanced file handling capabilities for Node.js applications. Now with full TypeScript support, universal JavaScript compatibility, and comprehensive error handling!
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- 📁 Flexible file storage configuration
|
|
8
|
-
- 🔒 Built-in file type validation
|
|
9
|
-
- 📦 Single and multiple file uploads
|
|
10
|
-
- 🎯 Field-specific file type restrictions
|
|
11
|
-
- 🗑️ File deletion utility
|
|
12
|
-
- ⚡ Configurable file size limits
|
|
13
|
-
- 🎨 Custom MIME type support
|
|
14
|
-
- 🔄 Unique file naming with UUID
|
|
15
|
-
- 🛡️ Path sanitization
|
|
16
|
-
- 📝 Comprehensive error handling with MultermateError
|
|
17
|
-
- 🔌 **Universal JavaScript compatibility** (CommonJS, ES Modules, TypeScript)
|
|
18
|
-
- 📘 Full TypeScript definitions and type safety
|
|
19
|
-
- 🌐 **Accept ANY file type** when no restrictions are specified
|
|
20
|
-
- 🎪 **Enhanced file type categories** (fonts, archives, CAD files, 3D models, etc.)
|
|
21
|
-
- 🚨 **Custom error classes** for better error handling
|
|
22
|
-
- 🔧 **Fixed form data processing** issues
|
|
23
|
-
|
|
24
|
-
## Installation
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
npm install multermate
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
## Universal JavaScript Compatibility
|
|
31
|
-
|
|
32
|
-
MulterMate works seamlessly across all JavaScript environments:
|
|
33
|
-
|
|
34
|
-
### CommonJS
|
|
35
|
-
|
|
36
|
-
```javascript
|
|
37
|
-
const {
|
|
38
|
-
uploadSingle,
|
|
39
|
-
uploadMultiple,
|
|
40
|
-
deleteFile,
|
|
41
|
-
MultermateError,
|
|
42
|
-
} = require("multermate");
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### ES Modules
|
|
46
|
-
|
|
47
|
-
```javascript
|
|
48
|
-
import {
|
|
49
|
-
uploadSingle,
|
|
50
|
-
uploadMultiple,
|
|
51
|
-
deleteFile,
|
|
52
|
-
MultermateError,
|
|
53
|
-
} from "multermate";
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### TypeScript
|
|
57
|
-
|
|
58
|
-
```typescript
|
|
59
|
-
import {
|
|
60
|
-
uploadSingle,
|
|
61
|
-
uploadMultiple,
|
|
62
|
-
deleteFile,
|
|
63
|
-
MultermateError,
|
|
64
|
-
UploadSingleOptions,
|
|
65
|
-
UploadMultipleOptions,
|
|
66
|
-
} from "multermate";
|
|
67
|
-
|
|
68
|
-
// With type definitions
|
|
69
|
-
const options: UploadSingleOptions = {
|
|
70
|
-
destination: "uploads/images",
|
|
71
|
-
fileTypes: ["images"],
|
|
72
|
-
fileSizeLimit: 5 * 1024 * 1024,
|
|
73
|
-
};
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
## Upload Configurations
|
|
77
|
-
|
|
78
|
-
### Accept ANY File Type
|
|
79
|
-
|
|
80
|
-
By default, when no `fileTypes` or `customMimeTypes` are specified, MulterMate accepts **ALL file types**:
|
|
81
|
-
|
|
82
|
-
```javascript
|
|
83
|
-
// Accept any file type - no restrictions!
|
|
84
|
-
app.post("/upload", uploadSingle(), (req, res) => {
|
|
85
|
-
res.json({ file: req.file });
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
// Also works with destination
|
|
89
|
-
app.post(
|
|
90
|
-
"/upload-any",
|
|
91
|
-
uploadSingle({
|
|
92
|
-
destination: "uploads/any-files",
|
|
93
|
-
filename: "uploaded-file",
|
|
94
|
-
// No fileTypes specified = accept all file types
|
|
95
|
-
}),
|
|
96
|
-
(req, res) => {
|
|
97
|
-
res.json({ file: req.file });
|
|
98
|
-
}
|
|
99
|
-
);
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### Single File Upload
|
|
103
|
-
|
|
104
|
-
```javascript
|
|
105
|
-
// Basic single file upload
|
|
106
|
-
app.post("/upload", uploadSingle(), (req, res) => {
|
|
107
|
-
if (req.fileValidationError) {
|
|
108
|
-
return res.status(400).json({ error: req.fileValidationError });
|
|
109
|
-
}
|
|
110
|
-
res.json({ file: req.file });
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
// Advanced single file upload with specific file types
|
|
114
|
-
app.post(
|
|
115
|
-
"/upload/advanced",
|
|
116
|
-
uploadSingle({
|
|
117
|
-
destination: "uploads/images",
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
}
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
"
|
|
175
|
-
"
|
|
176
|
-
"
|
|
177
|
-
"
|
|
178
|
-
"
|
|
179
|
-
"
|
|
180
|
-
"
|
|
181
|
-
"
|
|
182
|
-
"
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
188
|
-
)
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
"application/
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
)
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
|
302
|
-
|
|
|
303
|
-
|
|
|
304
|
-
|
|
|
305
|
-
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
|
317
|
-
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
|
322
|
-
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
##
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
1
|
+
# Multer Mate
|
|
2
|
+
|
|
3
|
+
A robust and flexible file upload utility built on top of Multer, providing advanced file handling capabilities for Node.js applications. Now with full TypeScript support, universal JavaScript compatibility, and comprehensive error handling!
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 📁 Flexible file storage configuration
|
|
8
|
+
- 🔒 Built-in file type validation
|
|
9
|
+
- 📦 Single and multiple file uploads
|
|
10
|
+
- 🎯 Field-specific file type restrictions
|
|
11
|
+
- 🗑️ File deletion utility
|
|
12
|
+
- ⚡ Configurable file size limits
|
|
13
|
+
- 🎨 Custom MIME type support
|
|
14
|
+
- 🔄 Unique file naming with UUID
|
|
15
|
+
- 🛡️ Path sanitization
|
|
16
|
+
- 📝 Comprehensive error handling with MultermateError
|
|
17
|
+
- 🔌 **Universal JavaScript compatibility** (CommonJS, ES Modules, TypeScript)
|
|
18
|
+
- 📘 Full TypeScript definitions and type safety
|
|
19
|
+
- 🌐 **Accept ANY file type** when no restrictions are specified
|
|
20
|
+
- 🎪 **Enhanced file type categories** (fonts, archives, CAD files, 3D models, etc.)
|
|
21
|
+
- 🚨 **Custom error classes** for better error handling
|
|
22
|
+
- 🔧 **Fixed form data processing** issues
|
|
23
|
+
|
|
24
|
+
## Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install multermate
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Universal JavaScript Compatibility
|
|
31
|
+
|
|
32
|
+
MulterMate works seamlessly across all JavaScript environments:
|
|
33
|
+
|
|
34
|
+
### CommonJS
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
const {
|
|
38
|
+
uploadSingle,
|
|
39
|
+
uploadMultiple,
|
|
40
|
+
deleteFile,
|
|
41
|
+
MultermateError,
|
|
42
|
+
} = require("multermate");
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### ES Modules
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
import {
|
|
49
|
+
uploadSingle,
|
|
50
|
+
uploadMultiple,
|
|
51
|
+
deleteFile,
|
|
52
|
+
MultermateError,
|
|
53
|
+
} from "multermate";
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### TypeScript
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import {
|
|
60
|
+
uploadSingle,
|
|
61
|
+
uploadMultiple,
|
|
62
|
+
deleteFile,
|
|
63
|
+
MultermateError,
|
|
64
|
+
UploadSingleOptions,
|
|
65
|
+
UploadMultipleOptions,
|
|
66
|
+
} from "multermate";
|
|
67
|
+
|
|
68
|
+
// With type definitions
|
|
69
|
+
const options: UploadSingleOptions = {
|
|
70
|
+
destination: "uploads/images",
|
|
71
|
+
fileTypes: ["images"],
|
|
72
|
+
fileSizeLimit: 5 * 1024 * 1024,
|
|
73
|
+
};
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Upload Configurations
|
|
77
|
+
|
|
78
|
+
### Accept ANY File Type
|
|
79
|
+
|
|
80
|
+
By default, when no `fileTypes` or `customMimeTypes` are specified, MulterMate accepts **ALL file types**:
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
// Accept any file type - no restrictions!
|
|
84
|
+
app.post("/upload", uploadSingle(), (req, res) => {
|
|
85
|
+
res.json({ file: req.file });
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Also works with destination
|
|
89
|
+
app.post(
|
|
90
|
+
"/upload-any",
|
|
91
|
+
uploadSingle({
|
|
92
|
+
destination: "uploads/any-files",
|
|
93
|
+
filename: "uploaded-file",
|
|
94
|
+
// No fileTypes specified = accept all file types
|
|
95
|
+
}),
|
|
96
|
+
(req, res) => {
|
|
97
|
+
res.json({ file: req.file });
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Single File Upload
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
// Basic single file upload
|
|
106
|
+
app.post("/upload", uploadSingle(), (req, res) => {
|
|
107
|
+
if (req.fileValidationError) {
|
|
108
|
+
return res.status(400).json({ error: req.fileValidationError });
|
|
109
|
+
}
|
|
110
|
+
res.json({ file: req.file });
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Advanced single file upload with specific file types
|
|
114
|
+
app.post(
|
|
115
|
+
"/upload/advanced",
|
|
116
|
+
uploadSingle({
|
|
117
|
+
destination: "uploads/images",
|
|
118
|
+
// Files are physically saved here, but req.file.path stays clean for DB
|
|
119
|
+
absoluteDestination: "C:/data/my-app/uploads/images",
|
|
120
|
+
filename: "profile",
|
|
121
|
+
fileTypes: ["images"],
|
|
122
|
+
fileSizeLimit: 5 * 1024 * 1024, // 5MB
|
|
123
|
+
preservePath: false,
|
|
124
|
+
}),
|
|
125
|
+
(req, res) => {
|
|
126
|
+
res.json({ file: req.file });
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Multiple Files Upload
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
|
+
// Multiple fields with different configurations
|
|
135
|
+
app.post(
|
|
136
|
+
"/upload/multiple",
|
|
137
|
+
uploadMultiple({
|
|
138
|
+
fields: [
|
|
139
|
+
{
|
|
140
|
+
name: "avatar",
|
|
141
|
+
maxCount: 1,
|
|
142
|
+
fileTypes: ["images"],
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: "documents",
|
|
146
|
+
maxCount: 5,
|
|
147
|
+
fileTypes: ["documents", "text"],
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: "any-files", // No fileTypes = accept any file type
|
|
151
|
+
maxCount: 3,
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
destination: "uploads/mixed",
|
|
155
|
+
absoluteDestination: "C:/data/my-app/uploads/mixed",
|
|
156
|
+
fileSizeLimit: 10 * 1024 * 1024, // 10MB per file
|
|
157
|
+
}),
|
|
158
|
+
(req, res) => {
|
|
159
|
+
res.json({ files: req.files });
|
|
160
|
+
}
|
|
161
|
+
);
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Enhanced File Type Categories
|
|
165
|
+
|
|
166
|
+
MulterMate now supports comprehensive file type categories:
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
app.post(
|
|
170
|
+
"/upload-comprehensive",
|
|
171
|
+
uploadSingle({
|
|
172
|
+
destination: "uploads/comprehensive",
|
|
173
|
+
fileTypes: [
|
|
174
|
+
"images", // JPEG, PNG, GIF, WebP, SVG, etc.
|
|
175
|
+
"videos", // MP4, AVI, MOV, WebM, etc.
|
|
176
|
+
"audio", // MP3, WAV, FLAC, AAC, etc.
|
|
177
|
+
"documents", // PDF, DOC, DOCX, XLS, XLSX, PPT, etc.
|
|
178
|
+
"text", // TXT, CSV, HTML, CSS, JS, MD, etc.
|
|
179
|
+
"archives", // ZIP, RAR, 7Z, TAR, GZIP, etc.
|
|
180
|
+
"fonts", // WOFF, WOFF2, TTF, OTF, etc.
|
|
181
|
+
"code", // JSON, XML, JS, TS, Python, etc.
|
|
182
|
+
"spreadsheets", // Excel, CSV files
|
|
183
|
+
"presentations", // PowerPoint, etc.
|
|
184
|
+
"cad", // CAD files
|
|
185
|
+
"models", // 3D model files
|
|
186
|
+
],
|
|
187
|
+
}),
|
|
188
|
+
(req, res) => {
|
|
189
|
+
res.json({ file: req.file });
|
|
190
|
+
}
|
|
191
|
+
);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Custom MIME Types
|
|
195
|
+
|
|
196
|
+
```javascript
|
|
197
|
+
app.post(
|
|
198
|
+
"/upload/custom",
|
|
199
|
+
uploadSingle({
|
|
200
|
+
destination: "uploads/custom",
|
|
201
|
+
customMimeTypes: [
|
|
202
|
+
"application/vnd.ms-excel",
|
|
203
|
+
"application/json",
|
|
204
|
+
"text/csv",
|
|
205
|
+
"application/x-custom-type",
|
|
206
|
+
],
|
|
207
|
+
fileSizeLimit: 1024 * 1024, // 1MB
|
|
208
|
+
}),
|
|
209
|
+
(req, res) => {
|
|
210
|
+
res.json({ file: req.file });
|
|
211
|
+
}
|
|
212
|
+
);
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Enhanced Error Handling
|
|
216
|
+
|
|
217
|
+
MulterMate now includes a custom `MultermateError` class for better error handling:
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
app.post("/upload", uploadSingle(), (req, res) => {
|
|
221
|
+
// Handle validation errors
|
|
222
|
+
if (req.fileValidationError) {
|
|
223
|
+
return res.status(400).json({
|
|
224
|
+
error: req.fileValidationError,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Handle missing files
|
|
229
|
+
if (!req.file) {
|
|
230
|
+
return res.status(400).json({
|
|
231
|
+
error: "No file uploaded",
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Success response
|
|
236
|
+
res.json({
|
|
237
|
+
success: true,
|
|
238
|
+
file: {
|
|
239
|
+
filename: req.file.filename,
|
|
240
|
+
path: req.file.path,
|
|
241
|
+
size: req.file.size,
|
|
242
|
+
mimetype: req.file.mimetype,
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Global error handler for MultermateError
|
|
248
|
+
app.use((err, req, res, next) => {
|
|
249
|
+
if (err instanceof MultermateError) {
|
|
250
|
+
return res.status(400).json({
|
|
251
|
+
success: false,
|
|
252
|
+
error: err.message,
|
|
253
|
+
code: err.code,
|
|
254
|
+
field: err.field,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Handle other errors
|
|
259
|
+
res.status(500).json({
|
|
260
|
+
success: false,
|
|
261
|
+
error: err.message,
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### File Deletion with Error Handling
|
|
267
|
+
|
|
268
|
+
```javascript
|
|
269
|
+
const { deleteFile, MultermateError } = require("multermate");
|
|
270
|
+
|
|
271
|
+
app.delete("/files/:filename", async (req, res) => {
|
|
272
|
+
try {
|
|
273
|
+
await deleteFile(`uploads/${req.params.filename}`);
|
|
274
|
+
res.json({
|
|
275
|
+
success: true,
|
|
276
|
+
message: "File deleted successfully",
|
|
277
|
+
});
|
|
278
|
+
} catch (error) {
|
|
279
|
+
if (error instanceof MultermateError) {
|
|
280
|
+
return res.status(400).json({
|
|
281
|
+
success: false,
|
|
282
|
+
error: error.message,
|
|
283
|
+
code: error.code,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
res.status(500).json({
|
|
288
|
+
success: false,
|
|
289
|
+
message: "Failed to delete file",
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## API Reference
|
|
296
|
+
|
|
297
|
+
### uploadSingle(options)
|
|
298
|
+
|
|
299
|
+
Configures single file upload with the following options:
|
|
300
|
+
|
|
301
|
+
| Option | Type | Default | Description |
|
|
302
|
+
| ------------------- | -------- | --------- | ------------------------------------------------------------------------------------------------ |
|
|
303
|
+
| destination | string | 'uploads' | Upload directory path |
|
|
304
|
+
| filename | string | 'file' | Form field name |
|
|
305
|
+
| fileTypes | string[] | [] | Allowed file type categories (empty = all) |
|
|
306
|
+
| customMimeTypes | string[] | [] | Custom MIME types |
|
|
307
|
+
| fileSizeLimit | number | 50MB | Max file size in bytes |
|
|
308
|
+
| preservePath | boolean | false | Preserve original path |
|
|
309
|
+
|
|
310
|
+
`absoluteDestination` (optional): Physical absolute directory for file storage. When provided, MulterMate keeps `req.file.path` relative so it is safer to store in DB.
|
|
311
|
+
|
|
312
|
+
### uploadMultiple(options)
|
|
313
|
+
|
|
314
|
+
Configures multiple file uploads with the following options:
|
|
315
|
+
|
|
316
|
+
| Option | Type | Default | Description |
|
|
317
|
+
| ------------------- | -------- | --------- | ----------------------------------------------------------------------------------------- |
|
|
318
|
+
| fields | Field[] | [] | Field configurations |
|
|
319
|
+
| destination | string | 'uploads' | Upload directory |
|
|
320
|
+
| customMimeTypes | string[] | [] | Custom MIME types |
|
|
321
|
+
| fileSizeLimit | number | 50MB | Max file size |
|
|
322
|
+
| preservePath | boolean | false | Preserve paths |
|
|
323
|
+
|
|
324
|
+
`absoluteDestination` (optional): Physical absolute directory for file storage. When provided, MulterMate keeps file paths in `req.files` relative for DB storage.
|
|
325
|
+
|
|
326
|
+
### Absolute Storage with Clean DB Path
|
|
327
|
+
|
|
328
|
+
Use `absoluteDestination` when files must be stored outside your app folder while keeping DB paths clean:
|
|
329
|
+
|
|
330
|
+
```javascript
|
|
331
|
+
app.post(
|
|
332
|
+
"/upload/absolute",
|
|
333
|
+
uploadSingle({
|
|
334
|
+
destination: "uploads/images", // This is what goes to req.file.path
|
|
335
|
+
absoluteDestination: "D:/cdn-storage/project/images", // Physical storage directory
|
|
336
|
+
fileTypes: ["images"],
|
|
337
|
+
}),
|
|
338
|
+
(req, res) => {
|
|
339
|
+
// Example:
|
|
340
|
+
// req.file.path => "uploads/images/<generated-file-name>.jpg"
|
|
341
|
+
// Physical file => "D:/cdn-storage/project/images/<generated-file-name>.jpg"
|
|
342
|
+
res.json({ file: req.file });
|
|
343
|
+
}
|
|
344
|
+
);
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
#### Field Configuration
|
|
348
|
+
|
|
349
|
+
| Option | Type | Default | Description |
|
|
350
|
+
| ------------- | -------- | ------- | ---------------------------------------- |
|
|
351
|
+
| name | string | - | Field name (required) |
|
|
352
|
+
| maxCount | number | 10 | Max files per field |
|
|
353
|
+
| fileTypes | string[] | [] | Allowed types (empty = accept all types) |
|
|
354
|
+
| fileSizeLimit | number | 50MB | Max file size |
|
|
355
|
+
|
|
356
|
+
### deleteFile(filePath)
|
|
357
|
+
|
|
358
|
+
Deletes a file from the filesystem:
|
|
359
|
+
|
|
360
|
+
| Parameter | Type | Description |
|
|
361
|
+
| --------- | ---------------- | ---------------- |
|
|
362
|
+
| filePath | string | Path to file |
|
|
363
|
+
| Returns | Promise<boolean> | Deletion success |
|
|
364
|
+
|
|
365
|
+
### MultermateError Class
|
|
366
|
+
|
|
367
|
+
Custom error class for better error handling:
|
|
368
|
+
|
|
369
|
+
```typescript
|
|
370
|
+
class MultermateError extends Error {
|
|
371
|
+
code?: string; // Error code (e.g., 'FILE_SIZE_LIMIT_EXCEEDED')
|
|
372
|
+
field?: string; // Field name that caused the error
|
|
373
|
+
storageErrors?: string[]; // Additional storage errors
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Supported File Type Categories
|
|
378
|
+
|
|
379
|
+
```javascript
|
|
380
|
+
const SUPPORTED_CATEGORIES = {
|
|
381
|
+
images: [
|
|
382
|
+
"image/jpeg",
|
|
383
|
+
"image/png",
|
|
384
|
+
"image/gif",
|
|
385
|
+
"image/webp",
|
|
386
|
+
"image/svg+xml",
|
|
387
|
+
"...",
|
|
388
|
+
],
|
|
389
|
+
videos: ["video/mp4", "video/avi", "video/mov", "video/webm", "..."],
|
|
390
|
+
audio: ["audio/mp3", "audio/wav", "audio/flac", "audio/aac", "..."],
|
|
391
|
+
documents: ["application/pdf", "application/msword", "..."],
|
|
392
|
+
text: ["text/plain", "text/csv", "text/html", "text/markdown", "..."],
|
|
393
|
+
archives: ["application/zip", "application/x-rar-compressed", "..."],
|
|
394
|
+
fonts: ["font/woff", "font/woff2", "font/ttf", "font/otf", "..."],
|
|
395
|
+
code: ["application/json", "text/javascript", "text/x-python", "..."],
|
|
396
|
+
spreadsheets: ["application/vnd.ms-excel", "text/csv", "..."],
|
|
397
|
+
presentations: ["application/vnd.ms-powerpoint", "..."],
|
|
398
|
+
cad: ["application/dwg", "application/dxf", "..."],
|
|
399
|
+
models: ["model/obj", "model/gltf+json", "..."],
|
|
400
|
+
pdfs: ["application/pdf"], // Backward compatibility
|
|
401
|
+
all: [
|
|
402
|
+
/* All supported MIME types */
|
|
403
|
+
],
|
|
404
|
+
};
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
## What's New in v2.1.0
|
|
408
|
+
|
|
409
|
+
### 🚀 Major Improvements
|
|
410
|
+
|
|
411
|
+
- **Universal JavaScript Compatibility**: Works seamlessly with CommonJS, ES Modules, and TypeScript
|
|
412
|
+
- **Accept ANY File Type**: When no `fileTypes` or `customMimeTypes` are specified, ALL file types are accepted
|
|
413
|
+
- **Enhanced File Categories**: Added support for fonts, CAD files, 3D models, and more
|
|
414
|
+
- **Custom Error Handling**: Introduced `MultermateError` class for better error management
|
|
415
|
+
- **Fixed Form Data Issues**: Resolved problems with form data processing
|
|
416
|
+
|
|
417
|
+
### 🔧 Technical Enhancements
|
|
418
|
+
|
|
419
|
+
- Improved module exports for better compatibility
|
|
420
|
+
- Enhanced MIME type detection and handling
|
|
421
|
+
- Better error propagation and handling
|
|
422
|
+
- Automatic directory creation
|
|
423
|
+
- More robust file filtering logic
|
|
424
|
+
|
|
425
|
+
### 📁 New File Type Categories
|
|
426
|
+
|
|
427
|
+
- **Fonts**: WOFF, WOFF2, TTF, OTF, EOT
|
|
428
|
+
- **CAD Files**: DWG, DXF, DWF
|
|
429
|
+
- **3D Models**: OBJ, GLTF, STL, PLY
|
|
430
|
+
- **Enhanced Archives**: 7Z, XZ, LZ4, LZMA
|
|
431
|
+
- **More Audio Formats**: OPUS, AMR, M4A
|
|
432
|
+
- **Extended Video Support**: MOV, WMV, FLV, MKV
|
|
433
|
+
|
|
434
|
+
## Migration from v2.0.x
|
|
435
|
+
|
|
436
|
+
The API remains backward compatible, but you can now take advantage of new features:
|
|
437
|
+
|
|
438
|
+
```javascript
|
|
439
|
+
// Old way (still works)
|
|
440
|
+
const { uploadSingle } = require("multermate");
|
|
441
|
+
|
|
442
|
+
// New way with error handling
|
|
443
|
+
const { uploadSingle, MultermateError } = require("multermate");
|
|
444
|
+
|
|
445
|
+
// Accept any file type (new in v2.1.0)
|
|
446
|
+
app.post("/upload-any", uploadSingle(), (req, res) => {
|
|
447
|
+
// No fileTypes specified = accepts ALL file types
|
|
448
|
+
res.json({ file: req.file });
|
|
449
|
+
});
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
## TypeScript Support
|
|
453
|
+
|
|
454
|
+
MulterMate includes complete TypeScript definitions:
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
import {
|
|
458
|
+
uploadSingle,
|
|
459
|
+
uploadMultiple,
|
|
460
|
+
deleteFile,
|
|
461
|
+
MultermateError,
|
|
462
|
+
UploadSingleOptions,
|
|
463
|
+
UploadMultipleOptions,
|
|
464
|
+
FieldConfig,
|
|
465
|
+
MIME_TYPES,
|
|
466
|
+
ALLOWED_FILE_TYPES,
|
|
467
|
+
} from "multermate";
|
|
468
|
+
|
|
469
|
+
// Type-safe configuration
|
|
470
|
+
const uploadOptions: UploadSingleOptions = {
|
|
471
|
+
destination: "uploads/safe",
|
|
472
|
+
fileTypes: ["images", "documents"],
|
|
473
|
+
fileSizeLimit: 10 * 1024 * 1024,
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
// Error handling with types
|
|
477
|
+
try {
|
|
478
|
+
await deleteFile(filePath);
|
|
479
|
+
} catch (error) {
|
|
480
|
+
if (error instanceof MultermateError) {
|
|
481
|
+
console.log(`Error ${error.code}: ${error.message}`);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
## Best Practices
|
|
487
|
+
|
|
488
|
+
1. **Always implement error handling** with MultermateError
|
|
489
|
+
2. **Set appropriate file size limits** for your use case
|
|
490
|
+
3. **Use specific file type restrictions** when security is important
|
|
491
|
+
4. **Leverage "accept any file type"** for general upload scenarios
|
|
492
|
+
5. **Implement proper file cleanup** mechanisms
|
|
493
|
+
6. **Create upload directories** beforehand (MulterMate does this automatically)
|
|
494
|
+
7. **Use TypeScript types** for better development experience
|
|
495
|
+
8. **Test with different JavaScript environments** (CommonJS, ESM, TypeScript)
|
|
496
|
+
|
|
497
|
+
## Testing
|
|
498
|
+
|
|
499
|
+
```bash
|
|
500
|
+
# Install dependencies
|
|
501
|
+
npm install
|
|
502
|
+
|
|
503
|
+
# Build the package
|
|
504
|
+
npm run build
|
|
505
|
+
|
|
506
|
+
# Run basic test
|
|
507
|
+
node test-improved.js
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
## License
|
|
511
|
+
|
|
512
|
+
MIT
|
|
513
|
+
|
|
514
|
+
## Contributing
|
|
515
|
+
|
|
516
|
+
Contributions are welcome! Please feel free to submit issues and pull requests.
|
|
517
|
+
|
|
518
|
+
## Author
|
|
519
|
+
|
|
520
|
+
Wasim Zaman
|
|
521
|
+
|
|
522
|
+
## Support
|
|
523
|
+
|
|
524
|
+
For support, please open an issue in the GitHub repository: <https://github.com/Wasim-Zaman/multermate>
|