Icons made by DinosoftLabs from www.flaticon.com





View -> Command Palette” and select the “Flutter: New Project” option: 1. Start Visual Studio Code. Go to menu “” and select the “Flutter: New Project” option:







web_upload.dart file. This is where we are going to work:





2. Create a folder called widgets inside the lib folder and create afile. This is where we are going to work:

3. Also, create a folder apps, and inside it create a main_app.dart file:





4. Remove anything from the main.dart file, import the main_app.dart file and call your main app: Remove anything from thefile, import thefile and call your main app:



import 'package:flutter/material.dart' import 'package:web_upload/apps/main_app.dart'

void main() => runApp(UploadApp());





main_app.dart and add a stateless widget that will return our main widget app: 5. This is great! Our Flutter Web App is coming to life! It might look like a lot of files/steps but this will be a structure of our app. Open theand add a stateless widget that will return our main widget app:



import 'package:flutter/material.dart' import 'package:web_upload/widgets/web_upload.dart'

class UploadApp extends StatelessWidget{

@override Widget build(BuildContext context) { return MaterialApp( title: 'My App' debugShowCheckedModeBanner: false theme: ThemeData( fontFamily: 'Quicksand' primarySwatch: Colors.purple, ), home: FileUploadApp(),

); }





web_upload.dart widget and create the FileUploadApp Stateful widget (a form will be in it). Copy the following code, and as you can see, we are returning a SafeArea with a Form in the body: 6. Open thewidget and create theStateful widget (a form will be in it). Copy the following code, and as you can see, we are returning awith a Form in the body:



import 'package:flutter/material.dart'

class FileUploadApp extends StatefulWidget { @override createState() => _FileUploadAppState();

class _FileUploadAppState extends { State @override Widget build(BuildContext context) { // TODO: implement build

return SafeArea( child: Scaffold( appBar: AppBar( title: Text( 'A Flutter Web file picker' ), ), body: Container( child: new Form( child: Padding( padding: const EdgeInsets.only(top: 16.0 , left: 28 ), child: new Container( width: 350 child: Column( [ children: ), ), ), ), ), ); } }





7. Sweet! Let’s see it working in the web browser:







column, and inside it a Widget, which will hold the upload button:



Column( crossAxisAlignment: CrossAxisAlignment.start, [ children: ] )

8. Inside our widget, create a better widget structure by adding a, and inside it a, which will hold the

9. Add a material button, which will be used to open up a dialog to select a file:



MaterialButton( color: Colors.pink, elevation: 8 highlightElevation: 2 shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular( 8 )), textColor: Colors.white, child: Text( 'Select a file' ), onPressed: () {}, ),

HTML library, Async library, Convert library and also the Typed Data library: 10. In order to be able to select a file in Flutter Web, import theand also the



import 'dart:html' as html; import 'dart:typed_data' import 'dart:async' import 'dart:convert' ; import 'package:http_parser/http_parser.dart'



startWebFilePicker and call the File Upload Input Element: 11. Create an async functionand call the



startWebFilePicker() async html.InputElement uploadInput = html.FileUploadInputElement(); uploadInput.multiple = true uploadInput.draggable = true uploadInput.click();





step 9, and in the onPressed event, call the startWebFilePicker function: 12. Go back to the material button created inand in the onPressed event, call the startWebFilePicker function:



onPressed: () { startWebFilePicker(); },





Web App right now, and click on the select file button, a file picker dialog will open: 14. If you start the, and click on the select file button, a file picker dialog will open:

variable that will hold the file as indexable collection of objects with a length, and also a fixed-length list variable:





List< int > _selectedFile;

Uint8List _bytesData; 15.So far, what we have done will only open the dialog but will not select the file. Let’s create a List





startWebFilePicker async function, and add an onChange listener in which we will get the file content as data URL: 16. Now, go back to the, and add anin which we will get the file content as data URL:



uploadInput.onChange.listen((e) { final files = uploadInput.files; final file = files[ 0 ]; final reader = new html.FileReader(); });





_handleResult function which will be called in the startWebFilePicker’s onChange listener so that it can convert the file as set is as bytes data: 17. Create awhich will be called in thelistener so that it can convert the file as set is as bytes data:



void _handleResult(Object result) { setState(() { _bytesData = Base64Decoder().convert(result.toString().split( "," ).last); _selectedFile = _bytesData; });



Note: With this method, to convert from Base64 to byte data, you MUST use .tostring().split(",").last otherwise you WILL NOT be able to send the file.





startWebFilePicker function, add a reader to load the file and call the data handler (our _handleResult function): 18. Inside thefunction, add a reader to load the file and call the data handler (ourfunction):



reader.onLoadEnd.listen((e) { _handleResult(reader.result); }); reader.readAsDataUrl(file);





19. The file selection is now ready. Let’s prepare our app to send the file to the server. First, prepare the form by creating a global form key:



GlobalKey _formKey = new (); GlobalKey





20. In the form, add the global key to the form and also set the autovalidation to true:



child: new Form( autovalidate: true , key: _formKey,





Upload button, add a Divider and another button that will call a function to send the file to the server on its onPressed event: 21. Below the, add aand anotherthe file to the server on its onPressed event:



Divider(color: Colors.teal,), RaisedButton( color: Colors.purple, elevation: 8.0 textColor: Colors.white, onPressed: () { makeRequest(); }, child: Text( 'Send file to server' ), ),





makeRequest (added to the send button in step 21): 22. Create a future async function called(added to the send button in):



Future makeRequest() async





HTTP library. Open your pubspecs.yaml file and add it as a dependency: 22. Before getting into the makeRequest function, you have to use the. Open yourfile and add it as a dependency:



http : ^0.12.0+2





web_upload.dart: 23. Import the library in the



import 'package:http/http.dart' as http;





makeRequest function, set your API url in a variable: 24. Now, in thefunction, set yourin a variable:



var url = Uri.parse( "http://192.168.23.10/upload_api/web/app_dev.php/api/save-file/" );





Create a request variable which will have the MultiPart Request:



var request = new http.MultipartRequest( "POST" , url); 25.Create avariable which will have the





step 17 the file was converted from base64 to a stream of bytes, and this was done because this is the only way right now to upload files. To send the file you need to use request.files.add and also use the HTTP library from step 22 like this: 26. Alright, this part is tricky since there almost no documentation about how to handle files with Flutter Web. Inthe file was converted from, and this was done because this is the only way right now to upload files. To send the file you need to useand also use thefromlike this:



request.files.add( await http.MultipartFile.fromBytes( 'file' , _selectedFile, contentType: new MediaType( 'application' , 'octet-stream' ), filename: "file_up" ));





http.MultipartFile.fromBytes





you cannot use dart:io, and you cannot use .fromPath No,, and





You must specify the content type. You could either detect the mime type of the file or just do it the KISS way like I did above





Note: I’m using a hard-coded word as the filename, you can extract the name in the startWebFilePicker function





27. Finally send the form and wait for a response:



request.send().then((response) { print( "test" ); print(response.statusCode); if (response.statusCode == 200 ) print( "Uploaded!" ); });





28. Finally, add a simple dialog to let the user know the file was uploaded:



showDialog( barrierDismissible: false context: context, child: new AlertDialog( title: new Text( "Details" ), //content: new Text("Hello World"), content: new SingleChildScrollView( child: new ListBody( [ children: new Text( "Upload successfull" ), ], ), ), [ actions: new FlatButton( child: new Text( 'Aceptar' ), onPressed: () { Navigator.pushAndRemoveUntil( context, MaterialPageRoute(builder: (context) => UploadApp()), (Route< dynamic > route) => false ); }, ), ], ));





29. That’s it! You now can upload files using Flutter Web!



















https://github.com/rjcalifornia/web_upload You can get the source code here:



If you want to know how the files are being handled in the backend, I used Symfony and MySQL.



Get the source code for the API here: https://github.com/rjcalifornia/file-upload-api If you want to know how the files are being handled in the backend, I used Symfony and MySQL.Get the source code for the API here:













For the last couple of weeks, I've been looking for a way to upload files with Flutter Web. I even opened two Github issues and also Reddit thread . I searched in StackOverflow and I only found examples with the dart:io library, which is not compatible with Flutter Web. Finally I found a way to send my files to an API, and it seemed to me that it wouldn't be bad to share my solution with others, just in case. That's why in this article I will give you a step-by-step guide on how to Upload Files to a server with Flutter Web