File Attachments
EndpointVault automatically captures file uploads from FormData requests when they fail. This ensures you don't lose user files when API calls fail.
The Problem
When you upload files using Dio's FormData with MultipartFile,
the file streams are consumed during request transmission. If the request fails,
you can't read the file data again — it's already gone.
EndpointVault solves this by capturing file data before the request is sent.
How It Works
1. Pre-request Capture
When a FormData request is detected, files are extracted and encrypted before transmission.
2. Transparent Replacement
The original FormData is replaced with a fresh copy containing new streams, so the actual request works normally.
3. On Success
Captured files are automatically cleaned up — no storage wasted.
4. On Failure
Files are included with the failure event and uploaded to the server for later analysis.
Basic Usage
File attachment capture is enabled by default. Just use FormData as usual:
final formData = FormData.fromMap({
'description': 'User profile photo',
'file': await MultipartFile.fromFile(
'/path/to/photo.jpg',
filename: 'photo.jpg',
),
});
// If this request fails, the file will be captured
await dio.post(
'/api/upload',
data: formData,
options: Options().critical(),
);
Configuration
Configure file attachment capture during SDK initialization:
await EndpointVault.init(
apiKey: 'your-api-key',
encryptionKey: 'your-encryption-key',
// File attachment options
captureFileAttachments: true, // Enable/disable (default: true)
maxAttachmentFileSize: 52428800, // Max single file: 50MB
maxTotalAttachmentSize: 104857600, // Max total per event: 100MB
maxAttachmentsPerEvent: 10, // Max files per event
attachmentRetentionDuration: Duration(days: 7),
attachmentStorageDir: null, // Custom path (optional)
);
Configuration Options
| Option | Default | Description |
|---|---|---|
captureFileAttachments |
true |
Enable or disable file capture |
maxAttachmentFileSize |
50 MB | Maximum size for a single file |
maxTotalAttachmentSize |
100 MB | Maximum total size per event |
maxAttachmentsPerEvent |
10 | Maximum number of files per event |
attachmentRetentionDuration |
7 days | How long to keep files locally |
Skipping Attachment Capture
You can skip file capture for specific requests:
// Skip attachment capture but still capture the request
await dio.post('/api/upload',
data: formData,
options: Options(extra: {'ev_skip_attachments': true}),
);
// Skip capture entirely
await dio.post('/api/upload',
data: formData,
options: Options().skipCapture(),
);
Interceptor Configuration
You can also configure file capture at the interceptor level:
dio.interceptors.add(EndpointVaultInterceptor(
captureFileAttachments: true, // Enable for this interceptor
// ... other options
));
Storage & Cleanup
- Files are encrypted using AES-256 before storage
- Stored in the app's documents directory by default
- Successful requests automatically delete captured files
- Old files are cleaned up based on
attachmentRetentionDuration
Manual cleanup:
// Clean up old attachments
await EndpointVault.instance.cleanupAttachments();
// Check storage usage
final bytes = await EndpointVault.instance.attachmentStorageBytes;
Limitations
- Files larger than
maxAttachmentFileSizeare skipped (not captured) - If total size exceeds
maxTotalAttachmentSize, remaining files are skipped - Maximum of
maxAttachmentsPerEventfiles per request - Very large files may impact app performance during extraction