diff --git a/packages/flet/lib/src/controls/file_picker.dart b/packages/flet/lib/src/controls/file_picker.dart
index 78b251c57..08b64e98a 100644
--- a/packages/flet/lib/src/controls/file_picker.dart
+++ b/packages/flet/lib/src/controls/file_picker.dart
@@ -6,9 +6,7 @@ import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:http/http.dart' as http;
 
-import '../flet_app_services.dart';
 import '../flet_control_backend.dart';
-import '../flet_server.dart';
 import '../models/control.dart';
 import '../utils/desktop.dart';
 import '../utils/strings.dart';
@@ -78,12 +76,12 @@ class FilePickerControl extends StatefulWidget {
   State<FilePickerControl> createState() => _FilePickerControlState();
 }
 
+List<PlatformFile> files = [];
+
 class _FilePickerControlState extends State<FilePickerControl>
     with FletStoreMixin {
   String? _state;
-  String? _upload;
   String? _path;
-  List<PlatformFile>? _files;
 
   @override
   Widget build(BuildContext context) {
@@ -108,11 +106,8 @@ class _FilePickerControlState extends State<FilePickerControl>
       }
 
       debugPrint("FilePicker _state: $_state, state: $state");
-
-      resetDialogState() {
-        _state = null;
-        widget.backend.updateControlState(widget.control.id, {"state": ""});
-      }
+      debugPrint("FilePicker _path: $_path");
+      debugPrint("FilePicker _files: $files");
 
       sendEvent() {
         if (defaultTargetPlatform != TargetPlatform.windows || !isDesktop()) {
@@ -123,8 +118,8 @@ class _FilePickerControlState extends State<FilePickerControl>
             "result",
             json.encode(FilePickerResultEvent(
                 path: _path,
-                files: _files
-                    ?.map((f) => FilePickerFile(
+                files: files
+                    .map((f) => FilePickerFile(
                         name: f.name,
                         path: kIsWeb ? null : f.path,
                         size: f.size))
@@ -133,9 +128,8 @@ class _FilePickerControlState extends State<FilePickerControl>
 
       if (_state != state) {
         _path = null;
-        _files = null;
+        // _files = null;
         _state = state;
-
         if (isDesktop() && defaultTargetPlatform == TargetPlatform.windows) {
           resetDialogState();
         }
@@ -154,7 +148,10 @@ class _FilePickerControlState extends State<FilePickerControl>
                   withReadStream: true)
               .then((result) {
             debugPrint("pickFiles() completed");
-            _files = result?.files;
+
+              if (result != null) {
+                files = result.files;
+              }
             sendEvent();
           });
         }
@@ -188,40 +185,39 @@ class _FilePickerControlState extends State<FilePickerControl>
             _path = result;
             sendEvent();
           });
+        } else if (state?.toLowerCase() == "uploadfiles" &&
+            upload != null &&
+            files.isNotEmpty) {
+          uploadFiles(upload, files, pageArgs.pageUri!);
         }
       }
-
-      // upload files
-      if (_upload != upload && upload != null && _files != null) {
-        _upload = upload;
-        uploadFiles(
-            upload, FletAppServices.of(context).server, pageArgs.pageUri!);
-      }
-
       return widget.nextChild ?? const SizedBox.shrink();
     });
   }
 
-  Future uploadFiles(String filesJson, FletServer server, Uri pageUri) async {
+  Future uploadFiles(
+      String filesJson, List<PlatformFile> files, Uri pageUri) async {
     var uj = json.decode(filesJson);
     var uploadFiles = (uj as List).map((u) => FilePickerUploadFile(
         name: u["name"], uploadUrl: u["upload_url"], method: u["method"]));
+    List<String> uploadedFiles = [];
     for (var uf in uploadFiles) {
-      var file = _files!.firstWhereOrNull((f) => f.name == uf.name);
+      var file = files.firstWhereOrNull((f) => f.name == uf.name);
       if (file != null) {
         try {
           await uploadFile(
-              file, server, getFullUploadUrl(pageUri, uf.uploadUrl), uf.method);
-          _files!.remove(file);
+              file, getFullUploadUrl(pageUri, uf.uploadUrl), uf.method);
+          uploadedFiles.add(file.name);
         } catch (e) {
-          sendProgress(server, file.name, null, e.toString());
+          sendProgress(file.name, null, e.toString());
         }
       }
     }
+    sendUploadFinishEvent(uploadedFiles);
+    resetDialogState();
   }
 
-  Future uploadFile(PlatformFile file, FletServer server, String uploadUrl,
-      String method) async {
+  Future uploadFile(PlatformFile file, String uploadUrl, String method) async {
     final fileReadStream = file.readStream;
     if (fileReadStream == null) {
       throw Exception('Cannot read file from null stream');
@@ -234,7 +230,7 @@ class _FilePickerControlState extends State<FilePickerControl>
     streamedRequest.contentLength = file.size;
 
     // send 0%
-    sendProgress(server, file.name, 0, null);
+    sendProgress(file.name, 0, null);
 
     double lastSent = 0; // send every 10%
     double progress = 0;
@@ -247,7 +243,7 @@ class _FilePickerControlState extends State<FilePickerControl>
       if (progress >= lastSent) {
         lastSent += 0.1;
         if (progress != 1.0) {
-          sendProgress(server, file.name, progress, null);
+          sendProgress(file.name, progress, null);
         }
       }
     }, onDone: () {
@@ -257,16 +253,20 @@ class _FilePickerControlState extends State<FilePickerControl>
     var streamedResponse = await streamedRequest.send();
     var response = await http.Response.fromStream(streamedResponse);
     if (response.statusCode < 200 || response.statusCode > 204) {
-      sendProgress(server, file.name, null,
+      sendProgress(file.name, null,
           "Upload endpoint returned code ${response.statusCode}: ${response.body}");
     } else {
       // send 100%
-      sendProgress(server, file.name, progress, null);
+      sendProgress(file.name, progress, null);
     }
   }
 
-  void sendProgress(
-      FletServer server, String name, double? progress, String? error) {
+  resetDialogState() {
+    _state = null;
+    widget.backend.updateControlState(widget.control.id, {"state": ""});
+  }
+
+  void sendProgress(String name, double? progress, String? error) {
     widget.backend.triggerControlEvent(
         widget.control.id,
         "upload",
@@ -274,6 +274,11 @@ class _FilePickerControlState extends State<FilePickerControl>
             name: name, progress: progress, error: error)));
   }
 
+  void sendUploadFinishEvent(List<String> files) {
+    widget.backend.triggerControlEvent(
+        widget.control.id, "upload_finished", json.encode(files));
+  }
+
   String getFullUploadUrl(Uri pageUri, String uploadUrl) {
     Uri uploadUri = Uri.parse(uploadUrl);
     if (!uploadUri.hasAuthority) {
diff --git a/sdk/python/packages/flet-core/src/flet_core/file_picker.py b/sdk/python/packages/flet-core/src/flet_core/file_picker.py
index beaa2963c..164630e0d 100644
--- a/sdk/python/packages/flet-core/src/flet_core/file_picker.py
+++ b/sdk/python/packages/flet-core/src/flet_core/file_picker.py
@@ -20,6 +20,7 @@ class FilePickerState(Enum):
     PICK_FILES = "pickFiles"
     SAVE_FILE = "saveFile"
     GET_DIRECTORY_PATH = "getDirectoryPath"
+    UPLOADING_FILES = "uploadfiles"
 
 
 class FilePickerFileType(Enum):
@@ -114,6 +115,7 @@ def __init__(
         self,
         on_result: Optional[Callable[[FilePickerResultEvent], None]] = None,
         on_upload: Optional[Callable[[FilePickerUploadEvent], None]] = None,
+        on_upload_finished: Optional[Callable[[ControlEvent], None]] = None,
         #
         # Control
         #
@@ -138,6 +140,11 @@ def convert_result_event_data(e):
         self.__on_upload = EventHandler(lambda e: FilePickerUploadEvent(e))
         self._add_event_handler("upload", self.__on_upload.get_handler())
 
+        self.__on_upload_finished = EventHandler(lambda e: e)
+        self._add_event_handler(
+            "upload_finished", self.__on_upload_finished.get_handler()
+        )
+
         self.__result: Optional[FilePickerResultEvent] = None
         self.__upload: List[FilePickerUploadFile] = []
         self.__allowed_extensions: Optional[List[str]] = None
@@ -145,6 +152,7 @@ def convert_result_event_data(e):
         self.__file_type = None
         self.on_result = on_result
         self.on_upload = on_upload
+        self.on_upload_finished = on_upload_finished
 
     def _get_control_name(self):
         return "filepicker"
@@ -248,6 +256,7 @@ async def get_directory_path_async(
 
     def upload(self, files: List[FilePickerUploadFile]):
         self.__upload = files
+        self.state = FilePickerState.UPLOADING_FILES
         self.update()
 
     @deprecated(
@@ -345,3 +354,12 @@ def on_upload(self):
     @on_upload.setter
     def on_upload(self, handler: OptionalEventCallable[FilePickerUploadEvent]):
         self.__on_upload.handler = handler
+
+    # on_upload_finished
+    @property
+    def on_upload_finished(self):
+        return self.__on_upload_finished.handler
+
+    @on_upload_finished.setter
+    def on_upload_finished(self, handler: OptionalEventCallable[ControlEvent]):
+        self.__on_upload_finished.handler = handler