Posted in API Dart Flutter PHP & MySQL

Flutter – How to pick file and upload to PHP server with progress percentage

Flutter – How to pick file and upload to PHP server with progress percentage Posted on May 19, 20203 Comments
I'm Hari Prasad Chaudhary from Nepal, developer of the finest educational website/app "MeroSpark" and the finest eCommerce system "PasalaY". Here I share the code snippet which I learn during development.

In this example, I have shown to pick any kind of file and upload it to the PHP server. During uploading, it will show progress percentage, total size, and uploaded size. See the example below and learn how to upload files to the PHP server and show progress percentage during uploading files. I have used REST API to communicate with the PHP server.

upload file progress

Server Side PHP Code: test/file_upload.php

<?php 
$return["error"] = false;
$return["msg"] = "";
$return["success"] = false;
//array to return

if(isset($_FILES["file"])){
    //directory to upload file
    $target_dir = "files/"; //create folder files/ to save file
    $filename = $_FILES["file"]["name"]; 
    //name of file
    //$_FILES["file"]["size"] get the size of file
    //you can validate here extension and size to upload file.

    $savefile = "$target_dir/$filename";
    //complete path to save file

    if(move_uploaded_file($_FILES["file"]["tmp_name"], $savefile)) {
        $return["error"] = false;
        //upload successful
    }else{
        $return["error"] = true;
        $return["msg"] =  "Error during saving file.";
    }
}else{
    $return["error"] = true;
    $return["msg"] =  "No file is sublitted.";
}

header('Content-Type: application/json');
// tell browser that its a json data
echo json_encode($return);
//converting array to JSON string
?>

Now flutter part, Add the file_picker, path, and dio Flutter package in your project by adding the following line in pubspec.yaml file.

dependencies:
  flutter:
    sdk: flutter
  file_picker: ^1.9.0+1
  dio: ^3.0.9
  path: ^1.6.4

Dart Code:

import 'dart:io';

import 'package:dio/dio.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:path/path.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return  MaterialApp(
         home: CustomFilePicker() //set the class here
    );
  }
}

class CustomFilePicker extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    return _CustomFilePicker();
  }
}

class _CustomFilePicker extends State<CustomFilePicker>{

  File selectedfile;
  Response response;
  String progress;
  Dio dio = new Dio();

  selectFile() async {
     selectedfile = await FilePicker.getFile(
          type: FileType.custom,
          allowedExtensions: ['jpg', 'pdf', 'mp4'],
          //allowed extension to choose
     );
     setState((){}); //update the UI so that file name is shown
  }

  uploadFile() async {
     String uploadurl = "http://192.168.0.112/test/file_upload.php";
     //dont use http://localhost , because emulator don't get that address
     //insted use your local IP address or use live URL
     //hit "ipconfig" in windows or "ip a" in linux to get you local IP

     FormData formdata = FormData.fromMap({
          "file": await MultipartFile.fromFile(
                 selectedfile.path, 
                 filename: basename(selectedfile.path) 
                 //show only filename from path
           ),
      });

      response = await dio.post(uploadurl, 
          data: formdata,
          onSendProgress: (int sent, int total) {
              String percentage = (sent/total*100).toStringAsFixed(2);
              setState(() {
                   progress = "$sent" + " Bytes of " "$total Bytes - " +  percentage + " % uploaded";
                   //update the progress
              });
          },);
          
      if(response.statusCode == 200){
            print(response.toString()); 
            //print response from server
      }else{ 
          print("Error during connection to server.");
      }
  }
  
  @override
  Widget build(BuildContext context) {
      return Scaffold(
         appBar: AppBar(
             title:Text("Select File and Upload"),
             backgroundColor: Colors.orangeAccent,
         ), //set appbar
         body:Container( 
            alignment: Alignment.center,
             padding: EdgeInsets.all(40),
             child:Column(children: <Widget>[

                  Container( 
                      margin: EdgeInsets.all(10),
                      //show file name here
                      child:progress == null?
                            Text("Progress: 0%"):
                            Text(basename("Progress: $progress"), 
                            textAlign: TextAlign.center,
                            style: TextStyle(fontSize: 18),),
                      //show progress status here
                  ),
                  
                  Container( 
                      margin: EdgeInsets.all(10),
                      //show file name here
                      child:selectedfile == null?
                            Text("Choose File"):
                            Text(basename(selectedfile.path)),
                      //basename is from path package, to get filename from path
                      //check if file is selected, if yes then show file name
                  ),

                  Container( 
                     child:RaisedButton.icon(
                       onPressed: (){
                         selectFile();
                       },
                       icon: Icon(Icons.folder_open), 
                       label: Text("CHOOSE FILE"),
                       color: Colors.redAccent,
                       colorBrightness: Brightness.dark,
                      )
                  ),

                  //if selectedfile is null then show empty container
                  //if file is selected then show upload button
                  selectedfile == null?
                  Container():
                  Container( 
                     child:RaisedButton.icon(
                       onPressed: (){ 
                         uploadFile();
                       }, 
                       icon: Icon(Icons.folder_open), 
                       label: Text("UPLOAD FILE"),
                       color: Colors.redAccent,
                       colorBrightness: Brightness.dark,
                      )
                  )
                  
             ],)
         )
      );
  }
}

In this way, you can upload file from flutter. Use this code base in your project and make your app great.

I'm Hari Prasad Chaudhary from Nepal, developer of the finest educational website/app "MeroSpark" and the finest eCommerce system "PasalaY". Here I share the code snippet which I learn during development.

3 comments

  1. Sir,It is very Helpful, using this method i can upload below 25mb files easily , above that i am facing http req404 error. what may be the solution?

Leave a Reply

Your email address will not be published. Required fields are marked *