I'll provide you with a complete implementation for file upload in Laravel API and Flutter client.

## Laravel API Implementation

### 1. Install Required Packages
```bash
composer require intervention/image
```

### 2. Create API Controller
```php
<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Intervention\Image\Facades\Image;

class FileUploadController extends Controller
{
    /**
     * Upload single file
     */
    public function upload(Request $request)
    {
        try {
            $request->validate([
                'file' => 'required|file|mimes:jpg,jpeg,png,pdf,doc,docx,xls,xlsx,txt|max:10240', // 10MB max
            ]);

            if (!$request->hasFile('file')) {
                return response()->json([
                    'success' => false,
                    'message' => 'No file uploaded'
                ], 400);
            }

            $file = $request->file('file');
            $originalName = $file->getClientOriginalName();
            $extension = $file->getClientOriginalExtension();
            $fileName = Str::random(20) . '_' . time() . '.' . $extension;
            $fileSize = $file->getSize();
            $mimeType = $file->getMimeType();

            // Store file
            $path = $file->store('uploads', 'public');

            // If it's an image, you can create thumbnail
            if (strpos($mimeType, 'image/') === 0) {
                $thumbnail = Image::make($file)
                    ->resize(300, 300, function ($constraint) {
                        $constraint->aspectRatio();
                    })
                    ->encode($extension, 80);
                
                Storage::disk('public')->put('thumbnails/' . $fileName, $thumbnail);
            }

            // Return response
            return response()->json([
                'success' => true,
                'message' => 'File uploaded successfully',
                'data' => [
                    'original_name' => $originalName,
                    'file_name' => $fileName,
                    'file_path' => Storage::url($path),
                    'thumbnail_path' => strpos($mimeType, 'image/') === 0 
                        ? Storage::url('thumbnails/' . $fileName) 
                        : null,
                    'file_size' => $fileSize,
                    'mime_type' => $mimeType,
                    'extension' => $extension,
                ]
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'File upload failed',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Upload multiple files
     */
    public function uploadMultiple(Request $request)
    {
        try {
            $request->validate([
                'files.*' => 'required|file|mimes:jpg,jpeg,png,pdf,doc,docx|max:10240',
            ]);

            if (!$request->hasFile('files')) {
                return response()->json([
                    'success' => false,
                    'message' => 'No files uploaded'
                ], 400);
            }

            $uploadedFiles = [];

            foreach ($request->file('files') as $file) {
                $originalName = $file->getClientOriginalName();
                $extension = $file->getClientOriginalExtension();
                $fileName = Str::random(20) . '_' . time() . '.' . $extension;
                $fileSize = $file->getSize();
                $mimeType = $file->getMimeType();

                $path = $file->store('uploads', 'public');

                $uploadedFiles[] = [
                    'original_name' => $originalName,
                    'file_name' => $fileName,
                    'file_path' => Storage::url($path),
                    'file_size' => $fileSize,
                    'mime_type' => $mimeType,
                ];
            }

            return response()->json([
                'success' => true,
                'message' => 'Files uploaded successfully',
                'data' => $uploadedFiles
            ]);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Files upload failed',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Delete file
     */
    public function delete(Request $request)
    {
        try {
            $request->validate([
                'file_path' => 'required|string',
            ]);

            $filePath = str_replace('/storage/', '', $request->file_path);
            
            if (Storage::disk('public')->exists($filePath)) {
                Storage::disk('public')->delete($filePath);
                
                // Delete thumbnail if exists
                $thumbnailPath = 'thumbnails/' . basename($filePath);
                if (Storage::disk('public')->exists($thumbnailPath)) {
                    Storage::disk('public')->delete($thumbnailPath);
                }

                return response()->json([
                    'success' => true,
                    'message' => 'File deleted successfully'
                ]);
            }

            return response()->json([
                'success' => false,
                'message' => 'File not found'
            ], 404);

        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'File deletion failed',
                'error' => $e->getMessage()
            ], 500);
        }
    }
}
```

### 3. Configure Storage
In `config/filesystems.php`:
```php
'disks' => [
    'public' => [
        'driver' => 'local',
        'root' => storage_path('app/public'),
        'url' => env('APP_URL').'/storage',
        'visibility' => 'public',
    ],
    // ...
],
```

Create symbolic link:
```bash
php artisan storage:link
```

### 4. Add API Routes
In `routes/api.php`:
```php
use App\Http\Controllers\Api\FileUploadController;

Route::middleware('auth:sanctum')->group(function () {
    Route::post('/upload', [FileUploadController::class, 'upload']);
    Route::post('/upload-multiple', [FileUploadController::class, 'uploadMultiple']);
    Route::delete('/delete-file', [FileUploadController::class, 'delete']);
});
```

## Flutter Implementation

### 1. Add Dependencies
In `pubspec.yaml`:
```yaml
dependencies:
  http: ^1.1.0
  dio: ^5.3.2
  file_picker: ^6.1.1
  image_picker: ^1.0.4
  permission_handler: ^10.4.4
  path_provider: ^2.1.1
  path: ^1.8.3
```

### 2. Flutter File Upload Service
```dart
import 'dart:io';
import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:file_picker/file_picker.dart';
import 'package:http/http.dart' as http;
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';

class ApiService {
  final String baseUrl = 'http://your-api-url.com/api';
  final Dio _dio = Dio();
  
  // For authentication (if needed)
  String? token;

  ApiService() {
    _dio.options.baseUrl = baseUrl;
    _dio.options.connectTimeout = Duration(seconds: 30);
    _dio.options.receiveTimeout = Duration(seconds: 30);
    
    // Add interceptors for auth
    _dio.interceptors.add(InterceptorsWrapper(
      onRequest: (options, handler) {
        if (token != null) {
          options.headers['Authorization'] = 'Bearer $token';
        }
        options.headers['Accept'] = 'application/json';
        return handler.next(options);
      },
    ));
  }

  // Upload single file
  Future<Map<String, dynamic>> uploadSingleFile(
    File file, {
    Map<String, dynamic>? additionalData,
    Function(int, int)? onSendProgress,
  }) async {
    try {
      String fileName = basename(file.path);
      
      FormData formData = FormData.fromMap({
        'file': await MultipartFile.fromFile(
          file.path,
          filename: fileName,
        ),
        ...?additionalData,
      });

      Response response = await _dio.post(
        '/upload',
        data: formData,
        onSendProgress: onSendProgress,
      );

      return response.data;
    } catch (e) {
      throw _handleError(e);
    }
  }

  // Upload multiple files
  Future<Map<String, dynamic>> uploadMultipleFiles(
    List<File> files, {
    Map<String, dynamic>? additionalData,
    Function(int, int)? onSendProgress,
  }) async {
    try {
      List<MultipartFile> multipartFiles = [];
      
      for (var file in files) {
        multipartFiles.add(
          await MultipartFile.fromFile(
            file.path,
            filename: basename(file.path),
          ),
        );
      }

      FormData formData = FormData.fromMap({
        'files': multipartFiles,
        ...?additionalData,
      });

      Response response = await _dio.post(
        '/upload-multiple',
        data: formData,
        onSendProgress: onSendProgress,
      );

      return response.data;
    } catch (e) {
      throw _handleError(e);
    }
  }

  // Delete file
  Future<Map<String, dynamic>> deleteFile(String filePath) async {
    try {
      Response response = await _dio.delete(
        '/delete-file',
        data: {'file_path': filePath},
      );

      return response.data;
    } catch (e) {
      throw _handleError(e);
    }
  }

  dynamic _handleError(dynamic error) {
    if (error is DioException) {
      if (error.response != null) {
        return error.response!.data;
      } else {
        return error.message;
      }
    }
    return error.toString();
  }
}
```

### 3. Flutter File Picker Widget
```dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';
import 'package:image_picker/image_picker.dart';

class FileUploadWidget extends StatefulWidget {
  final Function(List<File>)? onFilesSelected;
  final bool multiple;
  final List<String>? allowedExtensions;

  const FileUploadWidget({
    Key? key,
    this.onFilesSelected,
    this.multiple = false,
    this.allowedExtensions,
  }) : super(key: key);

  @override
  _FileUploadWidgetState createState() => _FileUploadWidgetState();
}

class _FileUploadWidgetState extends State<FileUploadWidget> {
  List<File> _selectedFiles = [];
  bool _isUploading = false;
  double _uploadProgress = 0;
  final ApiService _apiService = ApiService();

  Future<void> _pickFiles() async {
    try {
      FilePickerResult? result = await FilePicker.platform.pickFiles(
        allowMultiple: widget.multiple,
        type: FileType.custom,
        allowedExtensions: widget.allowedExtensions ?? 
          ['jpg', 'jpeg', 'png', 'pdf', 'doc', 'docx', 'xls', 'xlsx'],
      );

      if (result != null) {
        List<File> files = result.paths.map((path) => File(path!)).toList();
        setState(() {
          _selectedFiles = files;
        });
        
        if (widget.onFilesSelected != null) {
          widget.onFilesSelected!(files);
        }
      }
    } catch (e) {
      _showError('Error picking files: $e');
    }
  }

  Future<void> _pickImageFromCamera() async {
    try {
      final ImagePicker picker = ImagePicker();
      final XFile? image = await picker.pickImage(source: ImageSource.camera);
      
      if (image != null) {
        File file = File(image.path);
        setState(() {
          _selectedFiles = [file];
        });
        
        if (widget.onFilesSelected != null) {
          widget.onFilesSelected!([file]);
        }
      }
    } catch (e) {
      _showError('Error taking photo: $e');
    }
  }

  Future<void> _uploadFiles() async {
    if (_selectedFiles.isEmpty) return;

    setState(() {
      _isUploading = true;
      _uploadProgress = 0;
    });

    try {
      Map<String, dynamic> response;
      
      if (_selectedFiles.length == 1 && !widget.multiple) {
        response = await _apiService.uploadSingleFile(
          _selectedFiles.first,
          onSendProgress: (sent, total) {
            setState(() {
              _uploadProgress = sent / total;
            });
          },
        );
      } else {
        response = await _apiService.uploadMultipleFiles(
          _selectedFiles,
          onSendProgress: (sent, total) {
            setState(() {
              _uploadProgress = sent / total;
            });
          },
        );
      }

      setState(() {
        _isUploading = false;
        _uploadProgress = 0;
      });

      if (response['success'] == true) {
        _showSuccess('Files uploaded successfully!');
        setState(() {
          _selectedFiles.clear();
        });
      } else {
        _showError(response['message'] ?? 'Upload failed');
      }
    } catch (e) {
      setState(() {
        _isUploading = false;
        _uploadProgress = 0;
      });
      _showError('Upload error: $e');
    }
  }

  void _showSuccess(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
        backgroundColor: Colors.green,
      ),
    );
  }

  void _showError(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
        backgroundColor: Colors.red,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        // File selection buttons
        Row(
          children: [
            Expanded(
              child: ElevatedButton.icon(
                onPressed: _pickFiles,
                icon: Icon(Icons.folder_open),
                label: Text('Select Files'),
              ),
            ),
            SizedBox(width: 10),
            Expanded(
              child: ElevatedButton.icon(
                onPressed: _pickImageFromCamera,
                icon: Icon(Icons.camera_alt),
                label: Text('Take Photo'),
              ),
            ),
          ],
        ),
        
        SizedBox(height: 16),
        
        // Selected files list
        if (_selectedFiles.isNotEmpty)
          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                'Selected Files:',
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
              ..._selectedFiles.map((file) => ListTile(
                leading: Icon(Icons.insert_drive_file),
                title: Text(basename(file.path)),
                trailing: IconButton(
                  icon: Icon(Icons.close),
                  onPressed: () {
                    setState(() {
                      _selectedFiles.remove(file);
                    });
                  },
                ),
              )),
            ],
          ),
        
        SizedBox(height: 16),
        
        // Upload button and progress
        if (_selectedFiles.isNotEmpty)
          Column(
            children: [
              if (_isUploading)
                LinearProgressIndicator(
                  value: _uploadProgress,
                  backgroundColor: Colors.grey[200],
                  valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
                ),
              
              SizedBox(height: 10),
              
              ElevatedButton(
                onPressed: _isUploading ? null : _uploadFiles,
                style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.blue,
                  disabledBackgroundColor: Colors.grey,
                ),
                child: _isUploading
                    ? Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: [
                          CircularProgressIndicator(color: Colors.white),
                          SizedBox(width: 10),
                          Text('Uploading...'),
                        ],
                      )
                    : Text('Upload Files'),
              ),
            ],
          ),
      ],
    );
  }
}
```

### 4. Usage in Flutter Screen
```dart
import 'package:flutter/material.dart';

class UploadScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('File Upload'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            // Single file upload
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Single File Upload',
                      style: TextStyle(
                        fontSize: 18,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    SizedBox(height: 16),
                    FileUploadWidget(
                      multiple: false,
                      onFilesSelected: (files) {
                        print('Selected ${files.length} file(s)');
                      },
                    ),
                  ],
                ),
              ),
            ),
            
            SizedBox(height: 20),
            
            // Multiple file upload
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text(
                      'Multiple Files Upload',
                      style: TextStyle(
                        fontSize: 18,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    SizedBox(height: 16),
                    FileUploadWidget(
                      multiple: true,
                      onFilesSelected: (files) {
                        print('Selected ${files.length} file(s)');
                      },
                    ),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}
```

## Configuration Notes

### Laravel Configuration:
1. **CORS Configuration**: Install `fruitcake/laravel-cors` package
2. **File Size**: Adjust `upload_max_filesize` and `post_max_size` in php.ini
3. **Permissions**: Ensure storage directory has proper permissions

### Flutter Configuration:
1. **Android**: Add permissions in `AndroidManifest.xml`:
```xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.CAMERA"/>
```

2. **iOS**: Add permissions in `Info.plist`:
```xml
<key>NSPhotoLibraryUsageDescription</key>
<string>Need to access photos</string>
<key>NSCameraUsageDescription</key>
<string>Need to use camera</string>
<key>NSMicrophoneUsageDescription</key>
<string>Need to use microphone</string>
```

This implementation provides:
- Single and multiple file uploads
- Progress tracking
- Error handling
- File deletion
- Image thumbnails
- Cross-platform compatibility
- Proper error responses