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(),
);
Note: Files are encrypted using AES-256 before being stored on the device. Only you can decrypt them with your encryption key.

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

Manual cleanup:

// Clean up old attachments
await EndpointVault.instance.cleanupAttachments();

// Check storage usage
final bytes = await EndpointVault.instance.attachmentStorageBytes;

Limitations

Note: The following limitations apply to file capture: