Flutter

Flutter Web Image Upload Using dart:html and HTTP Request

๐Ÿ–ผ๏ธ Flutter Web Image Upload Using dart:html and HTTP Request

๐Ÿš€ Introduction

Uploading images in a Flutter Web application can be slightly different from mobile due to platform limitations. On the web, you don’t have access to the typical file pickers from mobile SDKs. Instead, you must rely on dart:html to interact with the browser and handle file selection.

In this tutorial, weโ€™ll build a simple Flutter Web app that allows the user to:

  • Select an image file from their device

  • Preview the image

  • Upload it to a remote server using a PHP API

Letโ€™s dive into the code and walk through each part!


๐Ÿ› ๏ธ Setting Up the Project

Start with a basic Flutter Web app. If you havenโ€™t already, enable web support:

flutter config --enable-web
flutter create image_upload_web
cd image_upload_web

Replace the contents of lib/main.dart with the code below.


๐Ÿ“„ Full Code

import 'dart:html' as html;
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Image Upload',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ImageUploadPage(),
    );
  }
}

class ImageUploadPage extends StatefulWidget {
  @override
  _ImageUploadPageState createState() => _ImageUploadPageState();
}

class _ImageUploadPageState extends State<ImageUploadPage> {
  Uint8List? _imageData;

  // Select image from device
  void _pickImage() async {
    final input = html.FileUploadInputElement()..accept = 'image/*';
    input.click();

    input.onChange.listen((e) async {
      final files = input.files;
      if (files!.isEmpty) return;

      final reader = html.FileReader();
      reader.readAsArrayBuffer(files[0]!);
      reader.onLoadEnd.listen((e) {
        setState(() {
          _imageData = reader.result as Uint8List;
        });
      });
    });
  }

  // Upload selected image to the server
  Future<void> _uploadImage() async {
    if (_imageData == null) {
      print('No image data to upload');
      return;
    }

    final request = http.MultipartRequest(
      'POST',
      Uri.parse('https://acesoftech.co.in/API/image_upload/image_upload.php'),
    );

    request.files.add(http.MultipartFile.fromBytes(
      'image',
      _imageData!,
      filename: 'image.jpg',
    ));

    try {
      final response = await request.send();
      if (response.statusCode == 200) {
        print('Image uploaded successfully');
      } else {
        print('Upload failed with status code ${response.statusCode}');
      }
    } catch (e) {
      print('An error occurred: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Image Upload')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            _imageData == null
                ? Text('No image selected.')
                : Image.memory(_imageData!),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _pickImage,
              child: Text('Pick Image'),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _uploadImage,
              child: Text('Upload Image'),
            ),
          ],
        ),
      ),
    );
  }
}

 


๐Ÿงฉ Explanation

๐Ÿ“ Picking the Image

We use dart:html‘s FileUploadInputElement to open the native browser file picker:

final input = html.FileUploadInputElement()..accept = 'image/*';
input.click();

Once the user selects an image, we read it using FileReader as a byte array (Uint8List) and store it in _imageData.


๐Ÿ“ค Uploading the Image

We use http.MultipartRequest to upload the image as a multipart form:

request.files.add(http.MultipartFile.fromBytes(
'image',
_imageData!,
filename: 'image.jpg',
));

โš ๏ธ Ensure your backend API (PHP in this case) is set up to handle multipart file uploads. The key 'image' should match the $_FILES['image'] field on your server.


๐Ÿ–ผ๏ธ Displaying the Image

If _imageData is available, we use Image.memory() to display a preview:

_imageData == null
? Text('No image selected.')
: Image.memory(_imageData!);

If you test this inย  IOS. it will throw error of html . so here is the modified code for IOS compatible also

 

import 'dart:typed_data';
import 'dart:io' as io;

import 'package:flutter/foundation.dart'; // for kIsWeb
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:http/http.dart' as http;

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Image Upload',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: ImageUploadPage(),
    );
  }
}

class ImageUploadPage extends StatefulWidget {
  @override
  _ImageUploadPageState createState() => _ImageUploadPageState();
}

class _ImageUploadPageState extends State<ImageUploadPage> {
  Uint8List? _imageData;
  XFile? _pickedFile;

  final ImagePicker _picker = ImagePicker();

  Future<void> _pickImage() async {
    final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
    if (image == null) return;

    setState(() {
      _pickedFile = image;
    });

    if (kIsWeb) {
      // For web, we need to read bytes
      final bytes = await image.readAsBytes();
      setState(() {
        _imageData = bytes;
      });
    } else {
      // For mobile, we can just display using the file
      final bytes = await image.readAsBytes();
      setState(() {
        _imageData = bytes;
      });
    }
  }

  Future<void> _uploadImage() async {
    if (_pickedFile == null) {
      print('No image selected');
      return;
    }

    final uri = Uri.parse('https://acesoftech.co.in/API/image_upload/image_upload.php');

    var request = http.MultipartRequest('POST', uri);

    if (kIsWeb) {
      request.files.add(
        http.MultipartFile.fromBytes(
          'image',
          _imageData!,
          filename: _pickedFile!.name,
        ),
      );
    } else {
      request.files.add(
        await http.MultipartFile.fromPath(
          'image',
          _pickedFile!.path,
        ),
      );
    }

    try {
      final response = await request.send();
      if (response.statusCode == 200) {
        print('Image uploaded successfully!');
      } else {
        print('Upload failed with status: ${response.statusCode}');
      }
    } catch (e) {
      print('Error uploading image: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    Widget imageWidget = _imageData == null
        ? Text('No image selected.')
        : Image.memory(_imageData!, height: 200);

    return Scaffold(
      appBar: AppBar(title: Text('Image Upload')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            imageWidget,
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _pickImage,
              child: Text('Pick Image'),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _uploadImage,
              child: Text('Upload Image'),
            ),
          ],
        ),
      ),
    );
  }
}

 

โœ… Summary

In this tutorial, we learned how to:

  • Use dart:html for file input in a Flutter Web project

  • Convert selected image data into bytes

  • Display a preview of the image using Image.memory

  • Upload the image to a server using http.MultipartRequest

This approach works great for basic web uploads and can be expanded to include drag-and-drop support, file size/type validation, upload progress bars, etc.

Leave a Reply

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