A simple way to upload a file to server from the flutter web app.

A simple way to upload a file to server from the flutter web app.

There might be a lot of articles about the same topic of uploading the file to a server from a flutter web app. But the approach I am taking is to use readily available plugins can concentrate on uploading the file by avoiding a lot of boilerplate code. Also if you have landed on this article which means you have passed the getting started guide. and trying to upload a file, so I have skipped getting started and adding the dependencies to pubsec and just added details only required for uploading the file.

1)  Choosing the right plugin.

I chose `file_picker_web: any` which is very simple to use and does not have much hassle to pick the file, and also avoids a lot of boilerplate code of writing the widget that triggers the file picker dialog.

below I have posted how to use the file picker

File file = await FilePicker.getFile();

Just wrap it up with any button having async action to pick the file .

2) Converting the Html file to bytes

As I have uses the plugin very specific to the web,  I have to convert the file to so that our Http packages support. So this function converts File object from HTML packages to bytes of  Uint8List which we use  for uploading  to a server

Future<Uint8List> _getHtmlFileContent(html.File blob) async {
    Uint8List file;
    final reader = FileReader();
    reader.readAsDataUrl(blob.slice(0, blob.size, blob.type));
    reader.onLoadEnd.listen((event) {
      Uint8List data =
          Base64Decoder().convert(reader.result.toString().split(",").last);
      file = data;
    }).onData((data) {
      file = Base64Decoder().convert(reader.result.toString().split(",").last);
      return file;
    });
    while (file == null) {
      await new Future.delayed(const Duration(milliseconds: 1));
      if (file != null) {
        break;
      }
    }
    return file;
  }

3) file uploading using of Http package

So the flutter's http packages support multipart form upload, which makes our life so much easier to upload the content

Uri uri = Uri.parse('$url/xxx--xxx/images/');
var request = http.MultipartRequest('POST', uri);
request.headers["<custom header>"] = "content";
request.fields['custom test field'] = "<your text field>";
request.filesadd(<httpMultipartfile>);
resquest.send();

The above code snippet provides stubs where we can add custom header, text fields, and http multipart files that we need to upload.

so the last part is to joining the small piece. the snippet to convert Html file to Http multipart file. so the snippet is pasted below

http.MultipartFile.fromBytes(
'fieldName', (await _getHtmlFileContent(file)),
filename: <filename with extension>)

Now We shall dive into complete example of uploading the file on press of the button.

RaisedButton(onPressed: () => _saveImage(),
              child: Text("Add Images"))
Button on click to trigger the action can be replaced with any action
_saveImage() async {
  File file = await FilePicker.getFile();
  
  if(file !=null) {
  		Uri uri = Uri.parse('$url/xxx--xxx/images/');
        var request = http.MultipartRequest('POST', uri);
        request.headers["<custom header>"] = "content";
        request.fields['custom test field'] = "<your text field>";
        request.filesadd(http.MultipartFile.fromBytes(
                       'image', (await _getHtmlFileContent(file)),
                       filename: file.name));
        resquest.send();
      }
  
 }
  
  
  Future<Uint8List> _getHtmlFileContent(html.File blob) async {
    Uint8List file;
    final reader = FileReader();
    reader.readAsDataUrl(blob.slice(0, blob.size, blob.type));
    reader.onLoadEnd.listen((event) {
      Uint8List data =
          Base64Decoder().convert(reader.result.toString().split(",").last);
      file = data;
    }).onData((data) {
      file = Base64Decoder().convert(reader.result.toString().split(",").last);
      return file;
    });
    while (file == null) {
      await new Future.delayed(const Duration(milliseconds: 1));
      if (file != null) {
        break;
      }
    }
    return file;
  }