W3Schools Learner's Blog

W3Schools Programming knowledge summary website

div

12/19/2021

How to upload Image using multipart in Flutter

 This post explains how to build a flutter application with the ability to select the image from the gallery using ImagePicker and upload images to the web server using a multi-part post request. A multipart request is an HTTP request that HTTP clients construct to send files and data over to a Server. It is commonly used by HTTP clients to upload files to the Server.

In this example, first, we choose the image from the gallery using ImagePicker and then upload images to the server using PHP.

First, add the image_picker Flutter package as a dependency by adding the following line in your pubspec.yaml file.

1
2
3
4
dependencies:
  flutter:
    sdk: flutter
  image_picker: ^0.6.7+11

Now write the function for pick image from Gallery. The optional parameter imageQuality accepts any value between 0 to 100, you can adjust it according to the size and quality required by your app. After obtaining the image file, we save it into the _imageFile variable and call setState() so that it can be displayed on the screen.

1
2
3
4
5
6
7
8
9
10
11
12
13
PickedFile _imageFile;
final ImagePicker _picker = ImagePicker();
 
  void _pickImage() async {
    try {
      final pickedFile = await _picker.getImage(source: ImageSource.gallery);
      setState(() {
        _imageFile = pickedFile;
      });
    } catch (e) {
      print("Image picker error " + e);
    }
  }

ImagePicker.pickImage() shows the familiar image picking screen and returns (through a Future) the path to the file the user picks. The FloatingActionButton is fairly simple.

1
2
3
4
5
floatingActionButton: FloatingActionButton(
        onPressed: _pickImage,
        tooltip: 'Pick Image from gallery',
        child: Icon(Icons.photo_library),
      ), // This traili

Next, let us create an image holder on the screen, which displays the selected image.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
Widget _previewImage() {
    if (_imageFile != null) {
      return Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Image.file(File(_imageFile.path)),
            SizedBox(
              height: 20,
            ),
            RaisedButton(
              onPressed: () async {
                var res = await uploadImage(_imageFile.path, uploadUrl);
                print(res);
              },
              child: const Text('Upload'),
            )
          ],
        ),
      );
    } else {
      return const Text(
        'You have not yet picked an image.',
        textAlign: TextAlign.center,
      );
    }
  }
 
 
 
  Future<void> retriveLostData() async {
    final LostData response = await _picker.getLostData();
    if (response.isEmpty) {
      return;
    }
    if (response.file != null) {
      setState(() {
        _imageFile = response.file;
      });
    } else {
      print('Retrieve error ' + response.exception.code);
    }
  }
 
@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
          child: FutureBuilder<void>(
        future: retriveLostData(),
        builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
          switch (snapshot.connectionState) {
            case ConnectionState.none:
            case ConnectionState.waiting:
              return const Text('Picked an image');
            case ConnectionState.done:
              return _previewImage();
            default:
              return const Text('Picked an image');
          }
        },
      )),
      floatingActionButton: FloatingActionButton(
        onPressed: _pickImage,
        tooltip: 'Pick Image from gallery',
        child: Icon(Icons.photo_library),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

Create MultipartFile

You can construct a multipart image file in 3 ways:

1.Default Constructor: You can use if you need to create the image from a Stream of bytes of which we know the length. Using the default constructor you could write a function like the following:

1
2
3
4
5
6
7
Future<String> uploadImage(filepath, url) async {
  var request = http.MultipartRequest('POST', Uri.parse(url));
  request.files.add(http.MultipartFile('image',
      File(filepath).readAsBytes().asStream(), File(filepath).lengthSync(),
      filename: filepath.split("/").last));
  var res = await request.send();
}

2.fromBytes: It attaches a file obtained from a List of bytes. Using MultipartFile.fromBytes() you could write a function like the following.

1
2
3
4
5
6
7
8
9
10
11
Future<String> uploadImage(filepath, url) async {
    var request = http.MultipartRequest('POST', Uri.parse(url));
    request.files.add(
        http.MultipartFile.fromBytes(
            'picture',
            File(filepath).readAsBytesSync(),
            filename: filepath.split("/").last
        )
    );
    var res = await request.send();
  }

3 fromPath: It attaches the file found at the given path. Using MultipartFile.fromPath() you could write a function like the following.

1
2
3
4
5
6
Future<String> uploadImage(filepath, url) async {
  var request = http.MultipartRequest('POST', Uri.parse(url));
  request.files.add(await http.MultipartFile.fromPath('image', filepath));
  var res = await request.send();
  return res.reasonPhrase;
}

Here we create a function and pass a file path and an URL then send that file to that URL with that multipart POST request. We use MultipartFile.fromPath() directly and return the status string of the request.

You could add regular text fields to a Multipart POST requests simply by add an item in the fields member Map:

1
request.fields['key'] = 'value';

Here’s the code for the call upload method.

1
2
3
4
5
6
7
RaisedButton(onPressed: () async {
              var res = await uploadImage(_imageFile.path,
              uploadUrl);
               print(res);
              },
              child: const Text('Upload'),
            )

We’ll write the very simple back-end code required to accept files this way in PHP after we’re done with the app. On the server-side is a simple PHP script, which takes the POST-File and stores it on the file system in the folder.

Download this code from GitHub

No comments:

Post a Comment

Note: only a member of this blog may post a comment.