multermate 1.1.0 → 1.1.1
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/dist/cjs/index.js +211 -0
- package/dist/esm/index.js +202 -0
- package/dist/esm/package.json +1 -0
- package/index.d.ts +1 -0
- package/index.js +2 -0
- package/index.mjs +15 -0
- package/package.json +48 -12
- package/readme.md +262 -86
- package/types/index.d.ts +58 -0
- package/babel.config.js +0 -12
- package/dist/index.cjs.js +0 -197
- package/dist/index.js +0 -158
- package/dist/index.mjs +0 -167
- package/src/index.js +0 -167
package/readme.md
CHANGED
|
@@ -1,159 +1,335 @@
|
|
|
1
1
|
# Multer Mate
|
|
2
2
|
|
|
3
|
-
|
|
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!
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
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
|
|
17
|
+
- 🔌 Works with CommonJS, ES Modules, and TypeScript
|
|
18
|
+
- 📘 Full TypeScript definitions and type safety
|
|
14
19
|
|
|
15
20
|
## Installation
|
|
16
21
|
|
|
17
|
-
Install the package using npm:
|
|
18
|
-
|
|
19
22
|
```bash
|
|
20
23
|
npm install multermate
|
|
21
24
|
```
|
|
22
25
|
|
|
23
|
-
## Usage
|
|
26
|
+
## Basic Usage
|
|
27
|
+
|
|
28
|
+
### CommonJS
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
const { uploadSingle, uploadMultiple, deleteFile } = require("multermate");
|
|
32
|
+
```
|
|
24
33
|
|
|
25
|
-
###
|
|
34
|
+
### ES Modules
|
|
26
35
|
|
|
27
36
|
```javascript
|
|
28
|
-
|
|
37
|
+
import { uploadSingle, uploadMultiple, deleteFile } from "multermate";
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### TypeScript
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import {
|
|
29
44
|
uploadSingle,
|
|
30
45
|
uploadMultiple,
|
|
31
|
-
|
|
32
|
-
|
|
46
|
+
deleteFile,
|
|
47
|
+
UploadSingleOptions,
|
|
48
|
+
UploadMultipleOptions,
|
|
49
|
+
} from "multermate";
|
|
50
|
+
|
|
51
|
+
// With type definitions
|
|
52
|
+
const options: UploadSingleOptions = {
|
|
53
|
+
destination: "uploads/images",
|
|
54
|
+
fileTypes: ["images"],
|
|
55
|
+
fileSizeLimit: 5 * 1024 * 1024,
|
|
56
|
+
};
|
|
33
57
|
```
|
|
34
58
|
|
|
59
|
+
## Upload Configurations
|
|
60
|
+
|
|
35
61
|
### Single File Upload
|
|
36
62
|
|
|
37
63
|
```javascript
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
64
|
+
// Basic single file upload
|
|
65
|
+
app.post("/upload", uploadSingle(), (req, res) => {
|
|
66
|
+
res.json({ file: req.file });
|
|
67
|
+
});
|
|
42
68
|
|
|
69
|
+
// Advanced single file upload
|
|
43
70
|
app.post(
|
|
44
|
-
"/upload/
|
|
71
|
+
"/upload/advanced",
|
|
45
72
|
uploadSingle({
|
|
46
73
|
destination: "uploads/images",
|
|
47
|
-
filename: "
|
|
74
|
+
filename: "profile",
|
|
48
75
|
fileTypes: ["images"],
|
|
49
|
-
fileSizeLimit:
|
|
76
|
+
fileSizeLimit: 5 * 1024 * 1024, // 5MB
|
|
77
|
+
preservePath: false,
|
|
50
78
|
}),
|
|
51
79
|
(req, res) => {
|
|
52
|
-
res.
|
|
80
|
+
res.json({ file: req.file });
|
|
53
81
|
}
|
|
54
82
|
);
|
|
55
|
-
|
|
56
|
-
app.listen(3000, () => {
|
|
57
|
-
console.log("Server started on http://localhost:3000");
|
|
58
|
-
});
|
|
59
83
|
```
|
|
60
84
|
|
|
61
|
-
### Multiple Files Upload
|
|
85
|
+
### Multiple Files Upload
|
|
62
86
|
|
|
63
87
|
```javascript
|
|
64
|
-
|
|
65
|
-
const { uploadMultiple } = require("multermate");
|
|
66
|
-
|
|
67
|
-
const app = express();
|
|
68
|
-
|
|
88
|
+
// Multiple fields with different configurations
|
|
69
89
|
app.post(
|
|
70
90
|
"/upload/multiple",
|
|
71
91
|
uploadMultiple({
|
|
72
92
|
fields: [
|
|
73
|
-
{
|
|
74
|
-
|
|
93
|
+
{
|
|
94
|
+
name: "avatar",
|
|
95
|
+
maxCount: 1,
|
|
96
|
+
fileTypes: ["images"],
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: "documents",
|
|
100
|
+
maxCount: 5,
|
|
101
|
+
fileTypes: ["pdfs"],
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: "media",
|
|
105
|
+
maxCount: 3,
|
|
106
|
+
fileTypes: ["images", "videos"],
|
|
107
|
+
},
|
|
75
108
|
],
|
|
109
|
+
destination: "uploads/mixed",
|
|
110
|
+
fileSizeLimit: 10 * 1024 * 1024, // 10MB per file
|
|
76
111
|
}),
|
|
77
112
|
(req, res) => {
|
|
78
|
-
res.
|
|
113
|
+
res.json({ files: req.files });
|
|
79
114
|
}
|
|
80
115
|
);
|
|
81
|
-
|
|
82
|
-
app.listen(3000, () => {
|
|
83
|
-
console.log("Server started on http://localhost:3000");
|
|
84
|
-
});
|
|
85
116
|
```
|
|
86
117
|
|
|
87
|
-
### Custom MIME Types
|
|
118
|
+
### Custom MIME Types
|
|
88
119
|
|
|
89
120
|
```javascript
|
|
90
|
-
const express = require("express");
|
|
91
|
-
const { uploadSingle, uploadMultiple } = require("multermate");
|
|
92
|
-
|
|
93
|
-
const app = express();
|
|
94
|
-
|
|
95
|
-
// Single PNG or PDF file upload
|
|
96
121
|
app.post(
|
|
97
|
-
"/upload
|
|
122
|
+
"/upload/custom",
|
|
98
123
|
uploadSingle({
|
|
99
124
|
destination: "uploads/custom",
|
|
100
|
-
customMimeTypes: [
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
res.send("PNG or PDF file uploaded!");
|
|
105
|
-
}
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
// Multiple PNGs or PDFs upload
|
|
109
|
-
app.post(
|
|
110
|
-
"/upload-custom-multiple",
|
|
111
|
-
uploadMultiple({
|
|
112
|
-
fields: [
|
|
113
|
-
{ name: "images", maxCount: 5, customMimeTypes: ["image/png"] },
|
|
114
|
-
{ name: "pdfs", maxCount: 2, customMimeTypes: ["application/pdf"] },
|
|
125
|
+
customMimeTypes: [
|
|
126
|
+
"application/vnd.ms-excel",
|
|
127
|
+
"application/json",
|
|
128
|
+
"text/csv",
|
|
115
129
|
],
|
|
130
|
+
fileSizeLimit: 1024 * 1024, // 1MB
|
|
116
131
|
}),
|
|
117
132
|
(req, res) => {
|
|
118
|
-
res.
|
|
133
|
+
res.json({ file: req.file });
|
|
119
134
|
}
|
|
120
135
|
);
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### File Deletion
|
|
121
139
|
|
|
122
|
-
|
|
123
|
-
|
|
140
|
+
```javascript
|
|
141
|
+
// Simple file deletion
|
|
142
|
+
app.delete("/files/:filename", async (req, res) => {
|
|
143
|
+
const isDeleted = await deleteFile(`uploads/${req.params.filename}`);
|
|
144
|
+
res.json({ success: isDeleted });
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Advanced file deletion with error handling
|
|
148
|
+
app.delete("/files/:type/:filename", async (req, res) => {
|
|
149
|
+
try {
|
|
150
|
+
const filePath = path.join("uploads", req.params.type, req.params.filename);
|
|
151
|
+
const isDeleted = await deleteFile(filePath);
|
|
152
|
+
|
|
153
|
+
if (isDeleted) {
|
|
154
|
+
res.json({
|
|
155
|
+
success: true,
|
|
156
|
+
message: "File deleted successfully",
|
|
157
|
+
});
|
|
158
|
+
} else {
|
|
159
|
+
res.status(404).json({
|
|
160
|
+
success: false,
|
|
161
|
+
message: "File not found or unable to delete",
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
} catch (error) {
|
|
165
|
+
res.status(500).json({
|
|
166
|
+
success: false,
|
|
167
|
+
message: error.message,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
124
170
|
});
|
|
125
171
|
```
|
|
126
172
|
|
|
127
|
-
|
|
173
|
+
## API Reference
|
|
174
|
+
|
|
175
|
+
### uploadSingle(options)
|
|
176
|
+
|
|
177
|
+
Configures single file upload with the following options:
|
|
178
|
+
|
|
179
|
+
| Option | Type | Default | Description |
|
|
180
|
+
| --------------- | -------- | --------- | ---------------------- |
|
|
181
|
+
| destination | string | 'uploads' | Upload directory path |
|
|
182
|
+
| filename | string | 'file' | Form field name |
|
|
183
|
+
| fileTypes | string[] | ['all'] | Allowed file types |
|
|
184
|
+
| customMimeTypes | string[] | [] | Custom MIME types |
|
|
185
|
+
| fileSizeLimit | number | 50MB | Max file size in bytes |
|
|
186
|
+
| preservePath | boolean | false | Preserve original path |
|
|
187
|
+
|
|
188
|
+
### uploadMultiple(options)
|
|
189
|
+
|
|
190
|
+
Configures multiple file uploads with the following options:
|
|
191
|
+
|
|
192
|
+
| Option | Type | Default | Description |
|
|
193
|
+
| --------------- | -------- | --------- | -------------------- |
|
|
194
|
+
| fields | Field[] | [] | Field configurations |
|
|
195
|
+
| destination | string | 'uploads' | Upload directory |
|
|
196
|
+
| customMimeTypes | string[] | [] | Custom MIME types |
|
|
197
|
+
| fileSizeLimit | number | 50MB | Max file size |
|
|
198
|
+
| preservePath | boolean | false | Preserve paths |
|
|
199
|
+
|
|
200
|
+
#### Field Configuration
|
|
201
|
+
|
|
202
|
+
| Option | Type | Default | Description |
|
|
203
|
+
| ------------- | -------- | ------- | --------------------- |
|
|
204
|
+
| name | string | - | Field name (required) |
|
|
205
|
+
| maxCount | number | 10 | Max files per field |
|
|
206
|
+
| fileTypes | string[] | ['all'] | Allowed types |
|
|
207
|
+
| fileSizeLimit | number | 50MB | Max file size |
|
|
208
|
+
|
|
209
|
+
### deleteFile(filePath)
|
|
210
|
+
|
|
211
|
+
Deletes a file from the filesystem:
|
|
212
|
+
|
|
213
|
+
| Parameter | Type | Description |
|
|
214
|
+
| --------- | ---------------- | ---------------- |
|
|
215
|
+
| filePath | string | Path to file |
|
|
216
|
+
| Returns | Promise<boolean> | Deletion success |
|
|
217
|
+
|
|
218
|
+
### Supported MIME Types
|
|
128
219
|
|
|
129
220
|
```javascript
|
|
130
|
-
const
|
|
131
|
-
|
|
221
|
+
const ALLOWED_MIME_TYPES = {
|
|
222
|
+
images: ["image/jpeg", "image/jpg", "image/png", "image/gif"],
|
|
223
|
+
videos: ["video/mp4", "video/mpeg", "video/ogg", "video/webm", "video/avi"],
|
|
224
|
+
pdfs: ["application/pdf"],
|
|
225
|
+
all: [
|
|
226
|
+
"image/jpeg",
|
|
227
|
+
"image/jpg",
|
|
228
|
+
"image/png",
|
|
229
|
+
"image/gif",
|
|
230
|
+
"video/mp4",
|
|
231
|
+
"video/mpeg",
|
|
232
|
+
"video/ogg",
|
|
233
|
+
"video/webm",
|
|
234
|
+
"video/avi",
|
|
235
|
+
"application/pdf",
|
|
236
|
+
],
|
|
237
|
+
};
|
|
238
|
+
```
|
|
132
239
|
|
|
133
|
-
|
|
240
|
+
## Error Handling
|
|
241
|
+
|
|
242
|
+
MulterMate adds a `fileValidationError` property to the request object when validation fails:
|
|
134
243
|
|
|
135
|
-
|
|
244
|
+
```javascript
|
|
136
245
|
app.post("/upload", uploadSingle(), (req, res) => {
|
|
137
|
-
|
|
246
|
+
try {
|
|
247
|
+
// File size validation
|
|
248
|
+
if (req.fileValidationError) {
|
|
249
|
+
return res.status(400).json({
|
|
250
|
+
error: req.fileValidationError,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// File existence check
|
|
255
|
+
if (!req.file) {
|
|
256
|
+
return res.status(400).json({
|
|
257
|
+
error: "No file uploaded",
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Success response
|
|
262
|
+
res.json({
|
|
263
|
+
success: true,
|
|
264
|
+
file: {
|
|
265
|
+
filename: req.file.filename,
|
|
266
|
+
path: req.file.path,
|
|
267
|
+
size: req.file.size,
|
|
268
|
+
mimetype: req.file.mimetype,
|
|
269
|
+
},
|
|
270
|
+
});
|
|
271
|
+
} catch (error) {
|
|
272
|
+
res.status(500).json({
|
|
273
|
+
error: error.message,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
138
276
|
});
|
|
277
|
+
```
|
|
139
278
|
|
|
140
|
-
|
|
141
|
-
app.post("/upload-multiple", uploadMultiple(), (req, res) => {
|
|
142
|
-
res.send("Files uploaded!");
|
|
143
|
-
});
|
|
279
|
+
## TypeScript Support
|
|
144
280
|
|
|
145
|
-
|
|
146
|
-
console.log("Server started on http://localhost:3000");
|
|
147
|
-
});
|
|
148
|
-
```
|
|
281
|
+
MulterMate includes complete TypeScript definitions for all functions and options:
|
|
149
282
|
|
|
150
|
-
|
|
283
|
+
```typescript
|
|
284
|
+
// Type definitions for all options
|
|
285
|
+
import {
|
|
286
|
+
UploadSingleOptions,
|
|
287
|
+
UploadMultipleOptions,
|
|
288
|
+
FieldConfig,
|
|
289
|
+
} from "multermate";
|
|
151
290
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
291
|
+
// Using with Express and TypeScript
|
|
292
|
+
import express from "express";
|
|
293
|
+
import { uploadSingle } from "multermate";
|
|
294
|
+
|
|
295
|
+
const app = express();
|
|
296
|
+
|
|
297
|
+
app.post(
|
|
298
|
+
"/upload",
|
|
299
|
+
uploadSingle({
|
|
300
|
+
destination: "uploads/typescript",
|
|
301
|
+
fileTypes: ["images"],
|
|
302
|
+
fileSizeLimit: 5 * 1024 * 1024,
|
|
303
|
+
}),
|
|
304
|
+
(req, res) => {
|
|
305
|
+
res.json({ success: true, file: req.file });
|
|
306
|
+
}
|
|
307
|
+
);
|
|
155
308
|
```
|
|
156
309
|
|
|
157
|
-
##
|
|
310
|
+
## Best Practices
|
|
311
|
+
|
|
312
|
+
1. Always implement proper error handling
|
|
313
|
+
2. Set appropriate file size limits
|
|
314
|
+
3. Validate file types on the server
|
|
315
|
+
4. Use custom storage destinations for different file types
|
|
316
|
+
5. Implement file cleanup mechanisms
|
|
317
|
+
6. Consider implementing file type verification beyond MIME types
|
|
318
|
+
7. Create upload directories if they don't exist (MulterMate does this automatically)
|
|
319
|
+
8. Use TypeScript types for better development experience
|
|
320
|
+
|
|
321
|
+
## License
|
|
322
|
+
|
|
323
|
+
MIT
|
|
324
|
+
|
|
325
|
+
## Contributing
|
|
326
|
+
|
|
327
|
+
Contributions are welcome! Please feel free to submit issues and pull requests.
|
|
328
|
+
|
|
329
|
+
## Author
|
|
330
|
+
|
|
331
|
+
Wasim Zaman
|
|
332
|
+
|
|
333
|
+
## Support
|
|
158
334
|
|
|
159
|
-
|
|
335
|
+
For support, please open an issue in the GitHub repository: https://github.com/Wasim-Zaman/multermate
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { NextFunction, Request, Response } from 'express';
|
|
2
|
+
export interface UploadSingleOptions {
|
|
3
|
+
destination?: string;
|
|
4
|
+
filename?: string;
|
|
5
|
+
fileTypes?: string[];
|
|
6
|
+
customMimeTypes?: string[];
|
|
7
|
+
fileSizeLimit?: number;
|
|
8
|
+
preservePath?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface FieldConfig {
|
|
11
|
+
name: string;
|
|
12
|
+
maxCount?: number;
|
|
13
|
+
fileTypes?: string[];
|
|
14
|
+
fileSizeLimit?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface UploadMultipleOptions {
|
|
17
|
+
fields: FieldConfig[];
|
|
18
|
+
destination?: string;
|
|
19
|
+
customMimeTypes?: string[];
|
|
20
|
+
fileSizeLimit?: number;
|
|
21
|
+
preservePath?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Function to handle a single file upload.
|
|
25
|
+
*
|
|
26
|
+
* @param options - Configuration options for the single file upload.
|
|
27
|
+
* @returns Multer middleware configured for single file upload.
|
|
28
|
+
*/
|
|
29
|
+
export declare function uploadSingle(options?: UploadSingleOptions): (req: Request, res: Response, next: NextFunction) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Function to handle multiple file uploads across multiple fields.
|
|
32
|
+
*
|
|
33
|
+
* @param options - Configuration options for multiple file uploads.
|
|
34
|
+
* @returns Multer middleware configured for multiple file uploads.
|
|
35
|
+
*/
|
|
36
|
+
export declare function uploadMultiple(options: UploadMultipleOptions): (req: Request, res: Response, next: NextFunction) => void;
|
|
37
|
+
/**
|
|
38
|
+
* Utility function to delete a file from the filesystem
|
|
39
|
+
*
|
|
40
|
+
* @param filePath - The path to the file that needs to be deleted
|
|
41
|
+
* @returns Promise that resolves to true if deletion was successful, false otherwise
|
|
42
|
+
*/
|
|
43
|
+
export declare function deleteFile(filePath: string): Promise<boolean>;
|
|
44
|
+
declare global {
|
|
45
|
+
namespace Express {
|
|
46
|
+
interface Request {
|
|
47
|
+
fileValidationError?: string;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export declare const ALLOWED_FILE_TYPES: string[];
|
|
52
|
+
declare const _default: {
|
|
53
|
+
uploadSingle: typeof uploadSingle;
|
|
54
|
+
uploadMultiple: typeof uploadMultiple;
|
|
55
|
+
deleteFile: typeof deleteFile;
|
|
56
|
+
ALLOWED_FILE_TYPES: string[];
|
|
57
|
+
};
|
|
58
|
+
export default _default;
|
package/babel.config.js
DELETED
package/dist/index.cjs.js
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
const path = require("path");
|
|
2
|
-
const multer = require("multer");
|
|
3
|
-
const { v4: uuidv4 } = require("uuid");
|
|
4
|
-
|
|
5
|
-
// Constants for allowed MIME types
|
|
6
|
-
const ALLOWED_MIME_TYPES = {
|
|
7
|
-
images: ["image/jpeg", "image/jpg", "image/png", "image/gif"],
|
|
8
|
-
videos: ["video/mp4", "video/mpeg", "video/ogg", "video/webm", "video/avi"],
|
|
9
|
-
pdfs: ["application/pdf"],
|
|
10
|
-
all: [
|
|
11
|
-
"image/jpeg",
|
|
12
|
-
"image/jpg",
|
|
13
|
-
"image/png",
|
|
14
|
-
"image/gif",
|
|
15
|
-
"video/mp4",
|
|
16
|
-
"video/mpeg",
|
|
17
|
-
"video/ogg",
|
|
18
|
-
"video/webm",
|
|
19
|
-
"video/avi",
|
|
20
|
-
"application/pdf",
|
|
21
|
-
],
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Function to configure storage for Multer.
|
|
26
|
-
*
|
|
27
|
-
* @param {string} destination - The destination folder where files will be stored. Default is "uploads".
|
|
28
|
-
* @returns {object} - Multer storage configuration object.
|
|
29
|
-
*/
|
|
30
|
-
const configureStorage = (destination) => {
|
|
31
|
-
return multer.diskStorage({
|
|
32
|
-
destination: (req, file, cb) => {
|
|
33
|
-
cb(null, destination || "uploads"); // Default folder is "uploads" if none is provided.
|
|
34
|
-
},
|
|
35
|
-
filename: (req, file, cb) => {
|
|
36
|
-
const sanitizedFilename = file.originalname.replace(/\\/g, "/");
|
|
37
|
-
const extension = path.extname(sanitizedFilename);
|
|
38
|
-
const fieldName = file.fieldname || "file"; // Use the field name as part of the filename.
|
|
39
|
-
const uniqueName = uuidv4(); // Generate a unique name using uuid.
|
|
40
|
-
let fileName = `${uniqueName}-${fieldName}${extension}`;
|
|
41
|
-
|
|
42
|
-
// Replace backslashes with forward slashes in the final filename
|
|
43
|
-
fileName = fileName.replace(/\\/g, "/");
|
|
44
|
-
|
|
45
|
-
cb(null, fileName); // Set the final filename.
|
|
46
|
-
},
|
|
47
|
-
});
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Function to configure file filter for Multer.
|
|
52
|
-
*
|
|
53
|
-
* @param {Array} allowedMimeTypes - Array of allowed MIME types.
|
|
54
|
-
* @returns {function} - File filter function for Multer.
|
|
55
|
-
*/
|
|
56
|
-
const configureFileFilter = (allowedMimeTypes) => {
|
|
57
|
-
return (req, file, cb) => {
|
|
58
|
-
if (allowedMimeTypes.includes(file.mimetype)) {
|
|
59
|
-
cb(null, true); // Allow the file if its MIME type is allowed.
|
|
60
|
-
} else {
|
|
61
|
-
cb(
|
|
62
|
-
new Error("Invalid file type. Only specified file types are allowed."),
|
|
63
|
-
false
|
|
64
|
-
); // Reject the file if its MIME type is not allowed.
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Function to configure Multer with the provided options.
|
|
71
|
-
*
|
|
72
|
-
* @param {object} options - Configuration options for Multer.
|
|
73
|
-
* @param {string} [options.destination] - Destination folder for files. Default is "uploads".
|
|
74
|
-
* @param {string} [options.filename] - Custom filename template for saved files.
|
|
75
|
-
* @param {Array<string>} [options.fileTypes] - Array of file types to allow (e.g., ['images', 'videos']).
|
|
76
|
-
* @param {Array<string>} [options.customMimeTypes] - Array of custom MIME types to allow.
|
|
77
|
-
* @param {number} [options.fileSizeLimit] - Maximum file size allowed (in bytes). Default is 50MB.
|
|
78
|
-
* @param {boolean} [options.preservePath] - Preserve the full path of files. Default is false.
|
|
79
|
-
* @returns {object} - Multer instance configured with the provided options.
|
|
80
|
-
*/
|
|
81
|
-
const configureMulter = ({
|
|
82
|
-
destination,
|
|
83
|
-
filename,
|
|
84
|
-
fileTypes = [],
|
|
85
|
-
customMimeTypes = [],
|
|
86
|
-
fileSizeLimit,
|
|
87
|
-
preservePath = false,
|
|
88
|
-
}) => {
|
|
89
|
-
const storage = configureStorage(destination);
|
|
90
|
-
|
|
91
|
-
// Combine allowed MIME types based on fileTypes array
|
|
92
|
-
let allowedMimeTypes = [];
|
|
93
|
-
|
|
94
|
-
if (customMimeTypes.length > 0) {
|
|
95
|
-
// Use custom MIME types if provided
|
|
96
|
-
allowedMimeTypes = customMimeTypes;
|
|
97
|
-
} else {
|
|
98
|
-
// Use default MIME types for specified fileTypes
|
|
99
|
-
fileTypes.forEach((type) => {
|
|
100
|
-
if (ALLOWED_MIME_TYPES[type]) {
|
|
101
|
-
allowedMimeTypes = allowedMimeTypes.concat(ALLOWED_MIME_TYPES[type]);
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
// If no specific file types are provided, use all allowed MIME types
|
|
106
|
-
if (allowedMimeTypes.length === 0) {
|
|
107
|
-
allowedMimeTypes = ALLOWED_MIME_TYPES.all;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
const fileFilter = configureFileFilter(allowedMimeTypes);
|
|
112
|
-
|
|
113
|
-
return multer({
|
|
114
|
-
storage,
|
|
115
|
-
fileFilter,
|
|
116
|
-
limits: { fileSize: fileSizeLimit || 1024 * 1024 * 50 }, // Default 50MB file size limit
|
|
117
|
-
preservePath,
|
|
118
|
-
});
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Function to handle multiple fields in a single form submission.
|
|
123
|
-
*
|
|
124
|
-
* @param {Array} fields - Array of field configurations, each containing:
|
|
125
|
-
* @param {string} fields.name - The name of the form field.
|
|
126
|
-
* @param {number} [fields.maxCount=10] - The maximum number of files to accept per field.
|
|
127
|
-
* @param {Array<string>} [fields.fileTypes] - Array of file types to allow for this field (e.g., ['images']).
|
|
128
|
-
* @returns {function} - Multer instance configured to handle multiple fields.
|
|
129
|
-
*/
|
|
130
|
-
const uploadFields = (fields) => {
|
|
131
|
-
const fieldConfigs = fields.map((field) => ({
|
|
132
|
-
name: field.name,
|
|
133
|
-
maxCount: field.maxCount || 10, // Default maxCount is 10 if not specified.
|
|
134
|
-
}));
|
|
135
|
-
|
|
136
|
-
let allowedFileTypes = [];
|
|
137
|
-
|
|
138
|
-
fields.forEach((field) => {
|
|
139
|
-
const types = field.fileTypes || [];
|
|
140
|
-
types.forEach((type) => {
|
|
141
|
-
if (ALLOWED_MIME_TYPES[type]) {
|
|
142
|
-
allowedFileTypes = allowedFileTypes.concat(ALLOWED_MIME_TYPES[type]);
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
const multerInstance = configureMulter({
|
|
148
|
-
fileTypes: allowedFileTypes,
|
|
149
|
-
customMimeTypes: [],
|
|
150
|
-
fileSizeLimit: fields[0]?.fileSizeLimit, // Assuming all fields share the same limit.
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
return multerInstance.fields(fieldConfigs);
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
// Export functions to configure multer and available file types
|
|
157
|
-
module.exports = {
|
|
158
|
-
/**
|
|
159
|
-
* Function to handle a single file upload.
|
|
160
|
-
*
|
|
161
|
-
* @param {object} options - Configuration options for the single file upload.
|
|
162
|
-
* @param {string} [options.destination] - Destination folder for the uploaded file.
|
|
163
|
-
* @param {string} [options.filename] - Custom filename template for the uploaded file.
|
|
164
|
-
* @param {Array<string>} [options.fileTypes] - Array of file types to allow (e.g., ['images']).
|
|
165
|
-
* @param {Array<string>} [options.customMimeTypes] - Array of custom MIME types to allow.
|
|
166
|
-
* @param {number} [options.fileSizeLimit] - Maximum file size allowed (in bytes). Default is 50MB.
|
|
167
|
-
* @param {boolean} [options.preservePath] - Preserve the full path of the uploaded file. Default is false.
|
|
168
|
-
* @returns {function} - Multer instance configured for single file upload.
|
|
169
|
-
*/
|
|
170
|
-
uploadSingle: (options = {}) => {
|
|
171
|
-
const multerInstance = configureMulter(options);
|
|
172
|
-
return multerInstance.single(options.filename || "file");
|
|
173
|
-
},
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Function to handle multiple file uploads across multiple fields.
|
|
177
|
-
*
|
|
178
|
-
* @param {object} options - Configuration options for multiple file uploads.
|
|
179
|
-
* @param {Array<object>} options.fields - Array of field configurations for multiple file uploads.
|
|
180
|
-
* @param {string} [options.destination] - Destination folder for the uploaded files.
|
|
181
|
-
* @param {Array<string>} [options.customMimeTypes] - Array of custom MIME types to allow.
|
|
182
|
-
* @param {number} [options.fileSizeLimit] - Maximum file size allowed (in bytes). Default is 50MB.
|
|
183
|
-
* @param {boolean} [options.preservePath] - Preserve the full path of the uploaded files. Default is false.
|
|
184
|
-
* @returns {function} - Multer instance configured for multiple file uploads.
|
|
185
|
-
*/
|
|
186
|
-
uploadMultiple: (options = {}) => {
|
|
187
|
-
const multerInstance = configureMulter(options);
|
|
188
|
-
return multerInstance.fields(options.fields || []);
|
|
189
|
-
},
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Export the allowed file types for reference.
|
|
193
|
-
*
|
|
194
|
-
* @type {Array<string>}
|
|
195
|
-
*/
|
|
196
|
-
ALLOWED_FILE_TYPES: Object.keys(ALLOWED_MIME_TYPES),
|
|
197
|
-
};
|