Embedded web server in Flutter

Chema March 13, 2019

embedded app flutter web server

Discover how to integrate a web server that allows uploading files in your app for Flutter (or server in Dart).

Motivation

In an app it is normal to connect to a web page or API to obtain information and / or send a form, telemetry information, etc.

But sometimes, there are projects where a mechanism is required to update the configuration or dynamic content without having direct access to the device (for example via WiFi).

In the case of iOS devices this is usually common in apps such as the VLC media player, where an embedded web server is created so that the user can easily upload its content (MKV, MP3, etc).

In our case, an app needed to be able to modify configuration files remotely.

Solution with http_server

We will use the http_server library developed by the Dart team.

The truth is that it is not well documented with examples but as you will see it is not complicated to put it into operation.

The first thing is to include the library as a dependency in our pubspec.yaml and run "flutter packages get" to update the dependencies.

	
	dependencies:
  ...
  http_server: ^0.9.8+1

 Then just include this code snippet in the root part of our main widget and call it from "initState()" for example.

	
	Future _startWebServer() async {
    runZoned(() {
      HttpServer.bind('0.0.0.0', 8000).then((server) {
        print('Server running at: ${server.address.address}');
        server.transform(HttpBodyHandler()).listen((HttpRequestBody body) async {
          print('Request URI');
          switch (body.request.uri.toString()) {
            case '/upload': {
              if (body.type != "form") {
                body.request.response.statusCode = 400;
                body.request.response.close();
                return;
              }
              for (var key in body.body.keys.toSet()) {
                if (key == "file") {
                  foundFile = true;
                }
              }
              if (!foundFile) {
                body.request.response.statusCode = 400;
                body.request.response.close();
                return;
              }
              HttpBodyFileUpload data = body.body['file'];
              // Save file
              final directory = await getApplicationDocumentsDirectory();
              File fFile = File('${directory.path}/file');
              fFile.writeAsBytesSync(data.content);
              body.request.response.statusCode = 201;
              body.request.response.close();
              break;
            }
            case '/':
              {
                String _content = await _loadStatic('index.html');
                body.request.response.statusCode = 200;
                body.request.response.headers.set("Content-Type", "text/html; charset=utf-8");
                body.request.response.write(_content);
                body.request.response.close();
                break;
              }
            default: {
              body.request.response.statusCode = 404;
              body.request.response.write('Not found');
              body.request.response.close();
            }
        }
        });
      });
    },
        onError: (e, stackTrace) => print('Oh noes! $e $stackTrace'));
  }

 

The code is easy to understand.
The first thing that is done is to create a server in any interface of the system under port 8000.
Then to the stream server we apply a transformation to handle "POST" that preprocesses form and files.
The last part is the handler for the subscription to the stream.
Here by means of a switch the index of the end point of rise is handled directly. For the root page, the static HTML content of a file in assets is loaded (function _loadStatic) and it is used.

In the file upload part, it is expected that the file is in the "file" field and as an example of processing it is saved as "file".

As you can see, in a few lines of code we have an embedded web server that accepts file uploads easily in Dart/Flutter.

 

Do not miss anything!

Subscribe to our mailing list and stay informed

Accept the terms & privacy conditions

Subscription done! Thanks so much

This website uses cookies

The cookies on this website are used to personalize content and analyze traffic. In addition, we share information about your use of the website with web analytics partners, who may combine it with other information you have provided or collected from your use of their services. You accept our cookies if you continue to use our website.
 

I agree See cookies

This website uses cookies

The cookies on this website are used to personalize content and analyze traffic. In addition, we share information about your use of the website with web analytics partners, who may combine it with other information you have provided or collected from your use of their services. You accept our cookies if you continue to use our website.