# Multer Utility

A comprehensive TypeScript wrapper for Multer with enhanced features including memory/disk storage, flexible configuration, and file management utilities.

## Features

- 🚀 **TypeScript Support** - Fully typed with comprehensive interfaces
- 💾 **Multiple Storage Options** - Memory and disk storage with easy switching
- 🔧 **Flexible Configuration** - Customizable file validation, naming, and storage options
- 🛡️ **Advanced Validation** - MIME type and extension validation with custom rules
- 📁 **File Management** - Built-in utilities for file operations and statistics
- 🎯 **Specialized Uploaders** - Pre-configured uploaders for images, audio, etc.
- 🔄 **Memory & Disk Storage** - Switch between storage types effortlessly

## Installation

```bash
npm install multer-utility
```

## Quick Start

### Basic Usage

```typescript
import { UploadService } from 'multer-utility';
import express from 'express';

const app = express();
const uploader = new UploadService();

// Single file upload
app.post('/upload', uploader.single('file'), (req, res) => {
  if (req.file) {
    const fileInfo = uploader.getFileInfo(req.file);
    res.json({ success: true, file: fileInfo });
  }
});
```

### Memory Storage

```typescript
import { createMemoryUploader } from 'multer-utility';

const memoryUploader = createMemoryUploader({
  maxFileSize: 1024 * 1024 * 10, // 10MB
  allowedMimeTypes: ['image/jpeg', 'image/png']
});

app.post('/upload-memory', memoryUploader.single('image'), (req, res) => {
  if (req.file) {
    // File is stored in memory as buffer
    const buffer = req.file.buffer;
    // Process the buffer as needed
    res.json({ success: true, size: buffer.length });
  }
});
```

### Custom Disk Storage

```typescript
import { createDiskUploader } from 'multer-utility';

const diskUploader = createDiskUploader('/custom/upload/path', {
  maxFileSize: 1024 * 1024 * 50, // 50MB
  useTimestamp: true,
  sanitizeFilenames: true
});
```

## Configuration Options

```typescript
interface UploadConfig {
  // Storage configuration
  storage?: 'disk' | 'memory';
  uploadDir?: string;
  
  // File validation
  allowedMimeTypes?: string[];
  allowedExtensions?: string[];
  maxFileSize?: number; // in bytes
  
  // Naming configuration
  useTimestamp?: boolean;
  sanitizeFilenames?: boolean;
  customNaming?: (file: Express.Multer.File) => string;
  
  // Advanced options
  createDirIfNotExists?: boolean;
  preserveOriginalName?: boolean;
}
```

## Advanced Usage

### Custom Configuration

```typescript
const uploader = new UploadService({
  storage: 'disk',
  uploadDir: './uploads/documents',
  allowedMimeTypes: ['application/pdf', 'image/jpeg', 'image/png'],
  allowedExtensions: ['.pdf', '.jpg', '.jpeg', '.png'],
  maxFileSize: 1024 * 1024 * 25, // 25MB
  useTimestamp: true,
  sanitizeFilenames: true,
  customNaming: (file) => `custom-${Date.now()}-${file.originalname}`
});
```

### Multiple File Upload

```typescript
// Array of files with same field name
app.post('/upload-multiple', uploader.array('files', 5), (req, res) => {
  if (req.files && Array.isArray(req.files)) {
    const fileInfos = req.files.map(file => uploader.getFileInfo(file));
    res.json({ success: true, files: fileInfos });
  }
});

// Multiple fields
app.post('/upload-fields', uploader.fields([
  { name: 'avatar', maxCount: 1 },
  { name: 'gallery', maxCount: 8 }
]), (req, res) => {
  const files = req.files as { [fieldname: string]: Express.Multer.File[] };
  res.json({ success: true, files });
});
```

### Pre-configured Uploaders

```typescript
import { createImageUploader, createAudioUploader } from 'multer-utility';

// Image uploader (JPEG, PNG, GIF, WebP)
const imageUploader = createImageUploader('./uploads/images');

// Audio uploader (MP3, WAV, OGG)
const audioUploader = createAudioUploader('./uploads/audio');

app.post('/upload-image', imageUploader.single('image'), (req, res) => {
  // Handle image upload
});

app.post('/upload-audio', audioUploader.single('audio'), (req, res) => {
  // Handle audio upload
});
```

## File Management

### File Operations

```typescript
const uploader = new UploadService({ storage: 'disk' });

// Check if file exists
const exists = uploader.fileExists('filename.jpg');

// Get file path
const filePath = uploader.getFilePath('filename.jpg');

// Delete file
const deleted = await uploader.deleteFile('filename.jpg');

// Get upload statistics
const stats = await uploader.getUploadStats();
console.log(stats);
// Output:
// {
//   totalFiles: 15,
//   totalSize: 2048576,
//   files: [
//     {
//       name: 'file1.jpg',
//       size: 102400,
//       created: '2023-01-01T00:00:00.000Z',
//       modified: '2023-01-01T00:00:00.000Z'
//     }
//   ]
// }
```

### File Validation

```typescript
const uploader = new UploadService();

// Validate file manually
const validation = uploader.validateFile(file);
if (!validation.isValid) {
  console.error(validation.error);
}
```

## Error Handling

```typescript
app.post('/upload', uploader.single('file'), (req, res) => {
  // Multer errors are automatically handled
  // Custom validation errors are thrown as MulterError
});

// Error handling middleware
app.use((error, req, res, next) => {
  if (error instanceof MulterError) {
    switch (error.code) {
      case 'LIMIT_FILE_SIZE':
        return res.status(400).json({ error: 'File too large' });
      case 'LIMIT_UNEXPECTED_FILE':
        return res.status(400).json({ error: 'Invalid file type' });
      default:
        return res.status(400).json({ error: error.message });
    }
  }
  next(error);
});
```

## Memory vs Disk Storage

### Memory Storage
- Files stored in memory as Buffer
- Faster access but limited by available RAM
- Good for small files or temporary processing
- Files don't persist after server restart

```typescript
const memoryUploader = createMemoryUploader();
// Access via req.file.buffer
```

### Disk Storage
- Files saved to filesystem
- Persistent storage
- Better for large files
- Includes file management utilities

```typescript
const diskUploader = createDiskUploader('./uploads');
// Access via req.file.path
```

## API Reference

### UploadService Class

#### Methods

- `single(fieldName: string)` - Handle single file upload
- `array(fieldName: string, maxCount?: number)` - Handle multiple files (same field)
- `fields(fields: multer.Field[])` - Handle multiple fields
- `any()` - Handle any files
- `none()` - No files expected
- `validateFile(file: Express.Multer.File)` - Validate file manually
- `getFileInfo(file: Express.Multer.File)` - Get detailed file information
- `deleteFile(filename: string)` - Delete file (disk storage only)
- `fileExists(filename: string)` - Check if file exists (disk storage only)
- `getFilePath(filename: string)` - Get file path (disk storage only)
- `getUploadStats()` - Get upload directory statistics
- `getConfig()` - Get current configuration

### Convenience Functions

- `createDiskUploader(uploadDir: string, config?: Partial<UploadConfig>)`
- `createMemoryUploader(config?: Partial<UploadConfig>)`
- `createImageUploader(uploadDir?: string)`
- `createAudioUploader(uploadDir?: string)`

## TypeScript Support

The package is fully typed and exports all necessary interfaces:

```typescript
import { 
  UploadService, 
  UploadConfig, 
  FileValidationResult,
  MulterError 
} from 'multer-utility';
```
## Author

[SURAJ] — suraj222615@gmail.com  
GitHub: [https://github.com/suraj-o](https://github.com/suraj-o)

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## License

MIT © [Suraj]

---

Made with ❤️ and TypeScript