FlutterFlow Custom Widget to Extract File name and Store Uploaded File in Local File.
Knowledge

FlutterFlow Custom Widget to Extract File name and Store Uploaded File in Local File.

Learn how to write Custom Widget to Extract File name and Store Uploaded File in Local File.

Pankaj Sharma
Flutterflow development company
January 6, 2025
Table of content

Problem Statement:-

When we upload any file in our local state in FF, so we are unable to extract proper name of that file. for example if we uploaded a file “abc.pdf”, so it will provide file name as “1745983544.pdf”, but we want “abc.pdf”.

There is also another way to extract file name, with the help of custom action, but in custom action we are unable to store  uploaded file in FF local state.

Why we can not achieve this via Custom Action:- The reason is data type of FF local state is FFUploadedFile and the custom action return a uploaded file as file type.

Solution:-

Here we are going to create custom widget, that perform file upload in local state and also save the file name in app state variable.

Note : - Here, we are creating a custom widget specifically for PDFs, but you can adapt it for any file extension as needed.

Here is some steps to resolve that issue : -

Step 1 : - Create a component with suitable name and create a local state variable. the type of the variable is Upload File (Bytes).

Here i created a component named as pdf_file_button_container.

Define a component state(Local state) variable with the Upload File (Bytes) data type named as uploadPdfFile.

Step 2 : - You can create a variable(String) to store the file name, either in the app state or the component state, based on your specific requirements.

Here i have created app state string variable named as uploadedPdfFileName.

Step 3 : - We will now create a custom button widget named as PdfFilePicker and integrate it seamlessly with our component.

Before creating a custom widget we need to import some files.

1. file_picker : - Need to add file_picker dependency in our custom widget.

import 'package:file_picker/file_picker.dart';

2. Import component path, because we need to update our local state varible(uploadPdfFile) in this custom widget.

import '../../components/pdf_file_button_container_model.dart';

export '../../components/pdf_file_button_container_model.dart';

3. In the code snippet below, we are updating the local state variable to store the file.

_model.uploadPdfFile = uploadedLocalFile;

       print("check here***");

       print(_model.uploadPdfFile);

       setState(() {});

       await widget.testAction?.call();

Step 4. In the snippet below, we are updating the app state variable to store the file name.

final file = pickedFiles.files.first;

 print("check name here");

 FFAppState().uploadedPdfFileName = file.name;

 print(file.name);

Step 5. Custom widget.

// Automatic FlutterFlow imports

import '/backend/schema/structs/index.dart';

import '/backend/supabase/supabase.dart';

import '/flutter_flow/flutter_flow_theme.dart';

import '/flutter_flow/flutter_flow_util.dart';

import '/custom_code/widgets/index.dart'; // Imports other custom widgets

import '/custom_code/actions/index.dart'; // Imports custom actions

import '/flutter_flow/custom_functions.dart'; // Imports custom functions

import 'package:flutter/material.dart';

// Begin custom widget code

// DO NOT REMOVE OR MODIFY THE CODE ABOVE!

import 'index.dart'; // Imports other custom widgets

import 'package:file_picker/file_picker.dart';

import '../../flutter_flow/flutter_flow_widgets.dart';

import '../../flutter_flow/upload_data.dart';

import '../../components/pdf_file_button_container_model.dart';

export '../../components/pdf_file_button_container_model.dart';

// import 'package:file_picker/file_picker.dart';

class PdfFilePicker extends StatefulWidget {

 const PdfFilePicker({

   super.key,

   this.width,

   this.height,

   required this.testAction,

 });

 final double? width;

 final double? height;

 final Future Function()? testAction;

 @override

 State<PdfFilePicker> createState() => _PdfFilePickerState();

}

class _PdfFilePickerState extends State<PdfFilePicker> {

 bool isDataUploading = false;

 FFUploadedFile uploadedLocalFile =

     FFUploadedFile(bytes: Uint8List.fromList([]));

 late PdfFileButtonContainerModel _model;

 void setState(VoidCallback callback) {

   super.setState(callback);

   _model.onUpdate();

 }

 void initState() {

   super.initState();

   _model = createModel(context, () => PdfFileButtonContainerModel());

   WidgetsBinding.instance.addPostFrameCallback((_) => setState(() {}));

 }

 @override

 Widget build(BuildContext context) {

   return FFButtonWidget(

     onPressed: () async {

       final selectedFiles = await selectFilesqq(

         allowedExtensions: ['pdf'],

         multiFile: false,

       );

       if (selectedFiles != null) {

         setState(() => isDataUploading = true);

         var selectedUploadedFiles = <FFUploadedFile>[];

         try {

           selectedUploadedFiles = selectedFiles

               .map((m) => FFUploadedFile(

                     name: m.storagePath.split('/').last,

                     bytes: m.bytes,

                   ))

               .toList();

         } finally {

           isDataUploading = false;

         }

         if (selectedUploadedFiles.length == selectedFiles.length) {

           setState(() {

             uploadedLocalFile = selectedUploadedFiles.first;

           });

         } else {

           setState(() {});

           return;

         }

       }

       _model.uploadPdfFile = uploadedLocalFile;

       print("check here***");

       print(_model.uploadPdfFile);

       setState(() {});

       await widget.testAction?.call();

     },

     text: 'Add Attachment',

     options: FFButtonOptions(

       height: 40.0,

       padding: EdgeInsetsDirectional.fromSTEB(24.0, 0.0, 24.0, 0.0),

       iconPadding: EdgeInsetsDirectional.fromSTEB(0.0, 0.0, 0.0, 0.0),

       color: FlutterFlowTheme.of(context).primary,

       textStyle: FlutterFlowTheme.of(context).titleSmall.override(

             fontFamily: 'Readex Pro',

             color: Colors.white,

             letterSpacing: 0.0,

           ),

       elevation: 3.0,

       borderSide: BorderSide(

         color: Colors.transparent,

         width: 1.0,

       ),

       borderRadius: BorderRadius.circular(8.0),

     ),

   );

 }

}

Future<SelectedFile?> selectFile({

 String? storageFolderPath,

 List<String>? allowedExtensions,

}) =>

   selectFilesqq(

     storageFolderPath: storageFolderPath,

     allowedExtensions: allowedExtensions,

     multiFile: false,

   ).then((value) => value?.first);

Future<List<SelectedFile>?> selectFilesqq({

 String? storageFolderPath,

 List<String>? allowedExtensions,

 bool multiFile = false,

}) async {

 final pickedFiles = await FilePicker.platform.pickFiles(

   type: allowedExtensions != null ? FileType.custom : FileType.any,

   allowedExtensions: allowedExtensions,

   withData: true,

   allowMultiple: multiFile,

 );

 if (pickedFiles == null || pickedFiles.files.isEmpty) {

   return null;

 }

 if (multiFile) {

   return Future.wait(pickedFiles.files.asMap().entries.map((e) async {

     final index = e.key;

     final file = e.value;

     final storagePath =

         _getStoragePath(storageFolderPath, file.name, false, index);

     return SelectedFile(

       storagePath: storagePath,

       filePath: isWeb ? null : file.path,

       bytes: file.bytes!,

     );

   }));

 }

 final file = pickedFiles.files.first;

 print("check name here");

 FFAppState().uploadedPdfFileName = file.name;

 print(file.name);

 if (file.bytes == null) {

   return null;

 }

 final storagePath = _getStoragePath(storageFolderPath, file.name, false);

 return [

   SelectedFile(

     storagePath: storagePath,

     filePath: isWeb ? null : file.path,

     bytes: file.bytes!,

   )

 ];

}

String _getStoragePath(

 String? pathPrefix,

 String filePath,

 bool isVideo, [

 int? index,

]) {

 pathPrefix = _removeTrailingSlash(pathPrefix);

 final timestamp = DateTime.now().microsecondsSinceEpoch;

 // Workaround fixed by https://github.com/flutter/plugins/pull/3685

 // (not yet in stable).

 final ext = isVideo ? 'mp4' : filePath.split('.').last;

 final indexStr = index != null ? '_$index' : '';

 return '$pathPrefix/$timestamp$indexStr.$ext';

}

String? _removeTrailingSlash(String? path) => path != null && path.endsWith('/')

   ? path.substring(0, path.length - 1)

   : path;

Conclusion:

In this document, we have addressed the issue of extracting the proper file name when uploading files to the local state in FlutterFlow (FF). By default, FF assigns a generic name to uploaded files, such as "1745983544.pdf" instead of the original file name like "abc.pdf". We explored a solution by creating a custom widget that performs the file upload, stores the file in the local state, and saves the original file name in the app state.

Through a step-by-step approach, we created a custom button widget that allows the selection of PDF files, stores the file in the component's state, and updates the app state with the correct file name. This solution is adaptable to other file types by modifying the allowed extensions as needed. By following the provided steps, developers can easily handle file uploads while ensuring the file name is retained accurately in FlutterFlow.

FlutterFlow Custom Widget to Extract File name and Store Uploaded File in Local File.

Ex- Technical Lead at Paytm Money | Senior Software Developer | NIT Surathkal

Flutterflow project image

Need expert help with custom solutions in Flutterflow?

Contact Us
Flutterflow development company

View more blogs

Ready to develop your own product? Get in touch today!

Get in Touch  
Flutterflow app development
Whatsapp icon