Universal File Picker

A cross-platform Flutter package for picking, previewing, and uploading files with a single, consistent API across Android, iOS, Web, macOS, Windows, and Linux.

Features

  • Cross-platform file picking - Works on all Flutter platforms
  • Unified file model - Single UFile class for all platforms
  • Smart preview system - Preview images, text files, PDFs, and more
  • Upload functionality - HTTP multipart uploads with progress tracking
  • Debug inspector - Built-in debugging tools for development
  • Camera support - Capture images directly on mobile devices
  • File filtering - Filter by extensions or MIME types
  • Multiple selection - Pick single or multiple files
  • Progress tracking - Real-time upload progress with cancellation support

Quick Start

Installation

Add to your pubspec.yaml:

dependencies:
  universal_file_picker: ^0.1.0

Basic Usage

import 'package:universal_file_picker/universal_file_picker.dart';

// Pick a single file
final file = await UniversalFilePicker().pickFile();

// Pick multiple files
final files = await UniversalFilePicker().pickFiles(
  options: const PickOptions(allowMultiple: true),
);

// Pick images with camera support
final images = await UniversalFilePicker().pickImages(
  allowMultiple: true,
  allowCamera: true,
);

// Preview a file
UFilePreview(file: file)

// Upload a file
final result = await file.upload(
  UploadOptions(url: 'https://api.example.com/upload'),
);

API Reference

File Picking

UniversalFilePicker().pickFile()

Pick a single file with default options.

UniversalFilePicker().pickFiles(options)

Pick multiple files with custom options.

UniversalFilePicker().pickImages(allowMultiple, allowCamera)

Pick images specifically, with optional camera support.

UniversalFilePicker().pickDocuments(allowMultiple, extensions)

Pick documents with optional extension filtering.

PickOptions

const PickOptions({
  bool allowMultiple = false,
  List<String>? allowedExtensions,
  List<String>? allowedMimeTypes,
  bool allowCamera = false,
  bool allowDirectory = false,
  bool generateThumbnails = true,
  int maxThumbnailSize = 100 * 1024,
})

File Preview

UFilePreview

A widget that automatically displays the appropriate preview based on file type:

UFilePreview(
  file: myFile,
  width: 300,
  height: 200,
  fit: BoxFit.contain,
  showFileInfo: true,
)

Supported preview types:

  • Images - Full image preview with zoom/pan
  • Text files - Inline text viewer with syntax highlighting
  • PDFs - PDF preview (requires optional adapter)
  • Other files - Fallback preview with "Open in System" option

File Upload

UFileUploader

Upload files with progress tracking and cancellation:

final uploader = UFileUploader();

// Upload single file
final result = await uploader.uploadFile(
  file: myFile,
  options: UploadOptions(url: 'https://api.example.com/upload'),
);

// Upload multiple files with progress
final results = await uploader.uploadBatchWithProgress(
  files: myFiles,
  options: UploadOptions(url: 'https://api.example.com/upload'),
  onProgress: (current, total, progress) {
    print('Uploaded $current of $total files (${(progress * 100).toStringAsFixed(1)}%)');
  },
);

// Cancel upload
uploader.cancel();

UploadOptions

const UploadOptions({
  required String url,
  Map<String, String>? headers,
  Map<String, String>? fields,
  String fieldName = 'file',
  int chunkSizeBytes = 1024 * 1024,
  Duration timeout = const Duration(minutes: 5),
})

Extension Methods

For convenience, the package provides extension methods:

// Upload a single file
final result = await myFile.upload(
  UploadOptions(url: 'https://api.example.com/upload'),
);

// Upload with progress
final result = await myFile.uploadWithProgress(
  UploadOptions(url: 'https://api.example.com/upload'),
  (progress) => print('Progress: ${(progress * 100).toStringAsFixed(1)}%'),
);

// Upload multiple files
final results = await myFiles.uploadAll(
  UploadOptions(url: 'https://api.example.com/upload'),
);

Debug Inspector

UFileInspector

A debug widget for visualizing picked files and upload results:

UFileInspector(
  files: pickedFiles,
  uploadResults: uploadResults,
  showUploadSection: true,
  showPreviewSection: true,
)

Complete Example

import 'package:flutter/material.dart';
import 'package:universal_file_picker/universal_file_picker.dart';

class FilePickerDemo extends StatefulWidget {
  @override
  _FilePickerDemoState createState() => _FilePickerDemoState();
}

class _FilePickerDemoState extends State<FilePickerDemo> {
  List<UFile> pickedFiles = [];
  List<UploadResult> uploadResults = [];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('File Picker Demo')),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(16),
        child: Column(
          children: [
            // Pick files
            ElevatedButton(
              onPressed: _pickFiles,
              child: Text('Pick Files'),
            ),
            
            // Show picked files
            if (pickedFiles.isNotEmpty) ...[
              SizedBox(height: 16),
              Text('Picked Files:'),
              ...pickedFiles.map((file) => ListTile(
                leading: Icon(Icons.file_present),
                title: Text(file.name),
                subtitle: Text('${file.size} bytes'),
              )),
              
              // Preview first file
              SizedBox(height: 16),
              UFilePreview(
                file: pickedFiles.first,
                height: 200,
              ),
              
              // Upload files
              SizedBox(height: 16),
              ElevatedButton(
                onPressed: _uploadFiles,
                child: Text('Upload Files'),
              ),
            ],
            
            // Debug inspector
            if (pickedFiles.isNotEmpty)
              UFileInspector(
                files: pickedFiles,
                uploadResults: uploadResults,
              ),
          ],
        ),
      ),
    );
  }

  Future<void> _pickFiles() async {
    final files = await UniversalFilePicker().pickFiles(
      options: const PickOptions(allowMultiple: true),
    );
    setState(() {
      pickedFiles = files;
    });
  }

  Future<void> _uploadFiles() async {
    final results = await pickedFiles.uploadAll(
      UploadOptions(url: 'https://httpbin.org/post'),
    );
    setState(() {
      uploadResults = results;
    });
  }
}

Platform Support

Note: Web support is planned for future versions. Currently, the package works on all native platforms (Android, iOS, macOS, Windows, Linux).

Platform File Picking Camera Directory Picking Drag & Drop
Android
iOS
Web
macOS
Windows
Linux

Dependencies

  • file_selector - For native file picking
  • image_picker - For camera functionality
  • http - For upload functionality

Roadmap

  • Web drag & drop support
  • PDF preview adapter
  • Video/audio preview
  • Cloud storage adapters (S3, Firebase)
  • Resumable uploads
  • File editing capabilities

Contributing

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

License

This project is licensed under the MIT License - see the LICENSE file for details.