Flutter Web - File chooser with drog and drop

Last updated Jun 17, 2021

In this flutter web example we will learn how to implement file choose in flutter web application. In this we can select file from file chooser option or drag and drop file in to drag area. To implement drag and drop feature we will using flutter_dropzone plugin. By using this feature we can upload files, images, video files etc.

A dropzone plugin is a web only plugin with use can easily implement drag and drop zone area.

 

Let's get started

Step 1: Create flutter application

 

Step 2: Add dropzone plugin in pubspec.yaml file

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_dropzone: ^2.0.1
  dotted_border: ^2.0.0

 

Step 3:Import flutter_dropzone.dart

import 'package:flutter_web_dragdrop/dropzone.dart';

 

Properties of DropZone widget

DropzoneView(
  onCreated: (controller) => this.controller = controller,
  onDrop: UploadedFile,
  onHover:() => setState(()=> highlight = true),
  onLeave: ()=> setState(()=>highlight = false),
)

 

onCreated: Attach a DropzoneController so that you ca control it & get data/information from event the user perform

onDrop: Whe user drop a file this function will hold all the data of file such as name, size, mime, URL path of file

onHover:  This Function will work when user hover a file on dropping zone in flutter web app

onLeave: Load when user is hover on dropzone and drop the file and leave it

 

DropzoneViewController

This plugin as option like filechoose to pick files, to do this we need to create DropzoneViewController instance ans call pick functionality by

late DropzoneViewController controller
final events = await controller.pickFiles()

 

The button event for pick file will be like below

 

ElevatedButton.icon(
  onPressed: () async {
    final events = await controller.pickFiles();
    if(events.isEmpty) return;
    UploadedFile(events.first);
  },
  icon: Icon(Icons.attach_file),
  label: Text(
    'Choose File',
    style: TextStyle(color: Colors.white, fontSize: 15),
  ),
  style: ElevatedButton.styleFrom(
      padding: EdgeInsets.symmetric(
          horizontal: 20
      ),
      primary: highlight? Colors.deepPurple: Colors.orange,
      shape: RoundedRectangleBorder()
  ),
)

 

Step 4: Run application

Flutter web file chooser example

 

This File chooser and drag and drop example contains below files

  1. dropzone.dart
  2. droped_file_zone.dart
  3. file_model.dart
  4. main.dart

 

dropzone.dart

import 'package:flutter_web_dragdrop/file_model.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dropzone/flutter_dropzone.dart';
import 'package:dotted_border/dotted_border.dart';

class DropZoneWidget extends StatefulWidget {

  final ValueChanged<File_Data_Model> onDroppedFile;

  const DropZoneWidget({Key? key,required this.onDroppedFile}):super(key: key);
  @override
  _DropZoneWidgetState createState() => _DropZoneWidgetState();
}

class _DropZoneWidgetState extends State<DropZoneWidget> {
  late DropzoneViewController controller;
  bool highlight = false;

  @override
  Widget build(BuildContext context) {

    return buildDecoration(

        child: Stack(
          children: [
            DropzoneView(
              onCreated: (controller) => this.controller = controller,
              onDrop: UploadedFile,
              onHover:() => setState(()=> highlight = true),
              onLeave: ()=> setState(()=>highlight = false),
            ),

            Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Icon(
                    Icons.cloud_upload_outlined,
                    size: 80,
                    color: Colors.white,
                  ),
                  Text(
                    'Drop Files Here',
                    style: TextStyle(color: Colors.white, fontSize: 24),
                  ),
                  const SizedBox(
                    height: 16,
                  ),
                  ElevatedButton.icon(
                    onPressed: () async {
                      final events = await controller.pickFiles();
                      if(events.isEmpty) return;
                      UploadedFile(events.first);
                    },
                    icon: Icon(Icons.attach_file),
                    label: Text(
                      'Choose File',
                      style: TextStyle(color: Colors.white, fontSize: 15),
                    ),
                    style: ElevatedButton.styleFrom(
                        padding: EdgeInsets.symmetric(
                            horizontal: 20
                        ),
                        primary: highlight? Colors.deepPurple: Colors.orange,
                        shape: RoundedRectangleBorder()
                    ),
                  )
                ],
              ),
            ),
          ],
        ));
  }

  Future UploadedFile(dynamic event) async {
    final name = event.name;

    final mime = await controller.getFileMIME(event);
    final byte = await controller.getFileSize(event);
    final url = await controller.createFileUrl(event);

    print('Name : $name');
    print('Mime: $mime');

    print('Size : ${byte / (1024 * 1024)}');
    print('URL: $url');

    final droppedFile = File_Data_Model
      (name: name, mime: mime, bytes: byte, url: url);

    widget.onDroppedFile(droppedFile);
    setState(() {
      highlight = false;
    });
  }

  Widget buildDecoration({required Widget child}){
    final colorBackground =  highlight? Colors.deepPurple: Colors.orange;
    return ClipRRect(
      borderRadius: BorderRadius.circular(12),
      child: Container(
        padding: EdgeInsets.all(10),
        child: DottedBorder(
            borderType: BorderType.RRect,
            color: Colors.white,
            strokeWidth: 3,
            dashPattern: [8,4],
            radius: Radius.circular(10),
            padding: EdgeInsets.zero,
            child: child
        ),
        color: colorBackground,
      ),
    );
  }
}

 

droped_file_zone.dart

import 'dart:js';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_web_dragdrop/file_model.dart';

class DroppedFileWidget extends StatelessWidget {

  final File_Data_Model? file;
  const DroppedFileWidget({Key? key, required this.file}) : super(key: key);

  @override
  Widget build(BuildContext context) {

    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Expanded(child: buildImage(context)),
      ],
    );
  }

  Widget buildImage(BuildContext context){
    if (file == null) return buildEmptyFile('No Selected File');

    print(file!.url);

    return Column(
      children: [
        if(file != null) buildFileDetail(file),
        Image.network(file!.url,
          width: MediaQuery.of(context).size.width ,
          height: MediaQuery.of(context).size.height,
          fit: BoxFit.cover,
          errorBuilder:(context,error,_)=>buildEmptyFile('No Preview'),
        ),
      ],
    );
  }

  Widget buildEmptyFile(String text){
    return Container(
      width: 120,
      height: 120,
      color: Colors.deepOrange,
      child: Center(child: Text(text)),
    );
  }

  Widget buildFileDetail(File_Data_Model? file) {
    final style = TextStyle( fontSize: 20);
    return Container(
      margin: EdgeInsets.only(left: 24),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        children: [
          Text('Selected File Preview ',style: TextStyle(fontWeight: FontWeight.w500,fontSize: 20),),
          Text('Name: ${file?.name}',style: TextStyle(fontWeight: FontWeight.w800,fontSize: 22),),
          const SizedBox(height: 10,),
          Text('Type: ${file?.mime}',style: style),
          const SizedBox(height: 10,),
          Text('Size: ${file?.size}',style: style),
          SizedBox(height: 20,)
        ],
      ),
    );
  }
}

 

file_model.dart

class File_Data_Model{
  final String name;
  final String mime;
  final int bytes;
  final String url;

  File_Data_Model({required this.name,required this.mime,required this.bytes, required this.url});

  String get size{
    final kb = bytes / 1024;
    final mb = kb / 1024;

    return mb > 1 ? '${mb.toStringAsFixed(2)} MB' : '${kb.toStringAsFixed(2)} KB';
  }

}

 

main.dart

import 'package:flutter/material.dart';
import 'package:flutter_web_dragdrop/dropzone.dart';
import 'package:flutter_web_dragdrop/droped_file_zone.dart';
import 'package:flutter_web_dragdrop/file_model.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dropzone/flutter_dropzone.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Flutter Demo',
        theme: ThemeData(

          primarySwatch: Colors.deepOrange,
        ),
        home: MyHomePage()
    );
  }
}

class MyHomePage extends StatefulWidget {


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

class _MyHomePageState extends State<MyHomePage> {

  File_Data_Model? file;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("drag drop flutter Web"),
      ),
      body: SingleChildScrollView(
        child: Container(
            alignment: Alignment.center,
            padding: EdgeInsets.all(15),
            child: Column(
              children: [

                Container(
                  height: 300,
                  child: DropZoneWidget(
                    onDroppedFile: (file) => setState(()=> this.file = file) ,
                  ),
                ),
                SizedBox(height: 20,),
                DroppedFileWidget(file:file ),

              ],
            )),
      ),
    );
  }
}

 

 

Article Contributed By :
https://www.rrtutors.com/site_assets/profile/assets/img/avataaars.svg

2392 Views