Creative Bracket

Implement your own File upload server

In this tutorial we will learn how to extract file data sent via a form and persist that to server’s filesystem. We will learn more about the multipart/form-data content type and how to use the mime package to extract images from our payload. Some great tips in this lesson so watch till the end!!!

Set up the project

Create a project folder and bootstrap a console-based project using Stagehand:

$ stagehand console-full

Open the pubspec.yaml file and add a dependency for the mime package:

dependencies:
  mime: ^0.9.6+3

Update your dependencies by running pub get in your terminal.

The solution

// main.dart

import 'dart:io';

import 'package:mime/mime.dart';

main() async {
  var server = await HttpServer.bind('localhost', 8085);

  server.listen((request) async {
    if (request.uri.path != '/fileupload') {
      request.response
        ..headers.contentType = ContentType.html
        ..write('''
          <html>
          <head>
            <title>Image Upload Server</title>
          </head>
          <body>
            <form method="post" action="/fileupload" enctype="multipart/form-data">
              <input type="file" name="fileupload" /><br /><br />
              <button type="submit">Upload to server</button>
            </form>
          </body>
          </html>
        ''');
    } else {
      // accessing /fileupload endpoint
      List<int> dataBytes = [];

      await for (var data in request) {
        dataBytes.addAll(data);
      }

      String boundary = request.headers.contentType.parameters['boundary'];
      final transformer = MimeMultipartTransformer(boundary);
      final uploadDirectory = './upload';

      final bodyStream = Stream.fromIterable([dataBytes]);
      final parts = await transformer.bind(bodyStream).toList();

      for (var part in parts) {
        print(part.headers);
        final contentDisposition = part.headers['content-disposition'];
        final filename = RegExp(r'filename="([^"]*)"')
            .firstMatch(contentDisposition)
            .group(1);
        final content = await part.toList();

        if (!Directory(uploadDirectory).existsSync()) {
          await Directory(uploadDirectory).create();
        }

        await File('$uploadDirectory/$filename').writeAsBytes(content[0]);
      }
    }

    await request.response.close();
  });
}

Sharing is caring 🤗

If you enjoyed reading this post, please share this through the various social buttons hovering on the left/top side of the screen ↖️⬆️. Also, check out and subscribe to my YouTube channel (hit the bell icon too) for videos on Dart.

Subscribe to the newsletter for my free 35-page Get started with Dart eBook and to be notified when new content is released.

Like, share and follow me 😍 for more content on Dart.

Jermaine Oppong

Hello 👋, I show programmers how to build full-stack web applications with the Dart SDK. I am passionate about teaching others, having received tremendous support on sites like dev.to and medium.com for my articles covering various aspects of the Dart language and ecosystem.

Useful learning materials