54

I would like to upload a image, I am using http.Client() for making requests,

static uploadImage(String id, File file) {
  var httpClient = createHttpClient();

  Map<String, String> headers = new Map<String, String>();
  headers.putIfAbsent("Authorization", () => "---");
  headers.putIfAbsent("Content-Type", () => "application/json");

  var body=new List();
  body.add(id.)
  httpClient.post(URL_UPLOADIMAGE,headers: headers,body: ,encoding: )
}

What should be the body and encoding part for the request ?

4
  • 1
    You should be able to use the same method from dart question! Commented Jun 30, 2017 at 9:14
  • that did it, however that answer is from older version of library. Commented Jun 30, 2017 at 11:12
  • 3
    request.files.add( new http.MultipartFile.fromBytes("file", file.readAsBytesSync(), filename: "Photo.jpg", contentType: new MediaType("image", "jpg"))); //this works now. Commented Jun 30, 2017 at 11:13
  • having same issue, will you share your solution? Commented Jun 1, 2018 at 2:37

16 Answers 16

68

Use MultipartRequest class

Upload(File imageFile) async {    
    var stream = new http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
      var length = await imageFile.length();

      var uri = Uri.parse(uploadURL);

     var request = new http.MultipartRequest("POST", uri);
      var multipartFile = new http.MultipartFile('file', stream, length,
          filename: basename(imageFile.path));
          //contentType: new MediaType('image', 'png'));

      request.files.add(multipartFile);
      var response = await request.send();
      print(response.statusCode);
      response.stream.transform(utf8.decoder).listen((value) {
        print(value);
      });
    }

name spaces:

import 'package:path/path.dart';
import 'package:async/async.dart';
import 'dart:io';
import 'package:http/http.dart' as http;
Sign up to request clarification or add additional context in comments.

10 Comments

My uploaded file is always application/octet-stream. Is there a way to get the right content type from the file and how can I set it in the request?
where do I import the MediaType class from
I figured I just had to import 'package:http_parser/http_parser.dart';
DelegatingStream.typed is deprecated.
USE var stream = new http.ByteStream(_image.openRead()); stream.cast(); INSTEAD of DelegatingStream.typed
|
31

The easiest way is to use the http library,

import 'dart:io';
import 'package:http/http.dart' as http;

_asyncFileUpload(String text, File file) async{
   //create multipart request for POST or PATCH method
   var request = http.MultipartRequest("POST", Uri.parse("<url>"));
   //add text fields
   request.fields["text_field"] = text;
   //create multipart using filepath, string or bytes
   var pic = await http.MultipartFile.fromPath("file_field", file.path);
   //add multipart to request
   request.files.add(pic);
   var response = await request.send();

   //Get the response from the server
   var responseData = await response.stream.toBytes();
   var responseString = String.fromCharCodes(responseData);
   print(responseString);
}

5 Comments

Hello , its giving me Unhandled Exception: SocketException: OS Error: Broken pipe, errno = 32 , please suggest
Please check the URL. Make sure you're able to post your file data from Postman
How do I receive it in my .php?
I am not much good at PHP but you can get files using $_FILES["file_field"]
@Santiago if am too late to answer you then it can help some one else. On the server side in my case i accepted it as a normal file from the HTML form and everything went well.
12

Checkout the body in submitForm() method.

File _image;

Future cameraImage() async {
  var image = await ImagePicker.pickImage(
    source: ImageSource.camera,
    maxHeight: 240.0,
    maxWidth: 240.0,
  );

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

submitForm() async {
  final response = await http.post(
    uri,
    headers: {
      AuthUtils.AUTH_HEADER: _authToken
    },
    body: {
      'user_id': userId
      'photo': _image != null ? 'data:image/png;base64,' +
          base64Encode(_image.readAsBytesSync()) : '',
    },
  );

  final responseJson = json.decode(response.body);

  print(responseJson);
}

3 Comments

How do I receive it in my .php?
@Santiago you need to decode and save. you can find solution here stackoverflow.com/questions/11511511/…
Base64 is easy but very bandwidth expensive... upto 30% rise in data to send... wouldnt recommend
10

I have tried all the above but none worked for me to upload a file to a server.

After a deep search, I got a plugin the same as Dio.

The following code uploads a file to a server.

uploadFileFromDio(UserProfile userProfile, File photoFile) async {
    var dio = new Dio();
    dio.options.baseUrl = url;
    dio.options.connectTimeout = 5000; //5s
    dio.options.receiveTimeout = 5000;
    dio.options.headers = <Header Json>;
    FormData formData = new FormData();
    formData.add("user_id", userProfile.userId);
    formData.add("name", userProfile.name);
    formData.add("email", userProfile.email);

    if (photoFile != null &&
        photoFile.path != null &&
        photoFile.path.isNotEmpty) {
      // Create a FormData
      String fileName = basename(photoFile.path);
      print("File Name : $fileName");
      print("File Size : ${photoFile.lengthSync()}");
      formData.add("user_picture", new UploadFileInfo(photoFile, fileName));
    }
    var response = await dio.post("user/manage_profile",
        data: formData,
        options: Options(
            method: 'POST',
            responseType: ResponseType.PLAIN // or ResponseType.JSON
            ));
    print("Response status: ${response.statusCode}");
    print("Response data: ${response.data}");
  }

8 Comments

Do you have any problems with content type? If I upload an image, I have to set the content type manually.
"content-type" is basically set in header of api, so you have to add a header param as content-type whatever set by api developer there Some common examples of content types are “text/plain”, “application/xml”, “text/html”, “application/json”, “image/gif”, and “image/jpeg”.
I am sending files (images, documents etc) from mobile device to Node.js API, which uses multer for storing files to MongoDB. I also have a web application which communicates with the same API. If I upload the image over my mobile app and Dio plugin, the mime-type on the server and in my mobgodb is "application/octet-stream". If I upload it over my web app, the mime-type is "image/jpeg". I do not need to set content-type manually in my web app.
I am uploading the image to the server but when I try to open an image that say's image is empty?
How do I receive it in my .php?
|
7

I found a working example without using any external plugin , this only uses

import 'package:http/http.dart' as http;

Code

var stream =
        new http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
    // get file length
    var length = await imageFile.length(); //imageFile is your image file
    Map<String, String> headers = {
      "Accept": "application/json",
      "Authorization": "Bearer " + token
    }; // ignore this headers if there is no authentication

    // string to uri
    var uri = Uri.parse(Constants.BASE_URL + "api endpoint here");

    // create multipart request
    var request = new http.MultipartRequest("POST", uri);

  // multipart that takes file
    var multipartFileSign = new http.MultipartFile('profile_pic', stream, length,
        filename: basename(imageFile.path));

    // add file to multipart
    request.files.add(multipartFileSign);

    //add headers
    request.headers.addAll(headers);

    //adding params
    request.fields['loginId'] = '12';
    request.fields['firstName'] = 'abc';
   // request.fields['lastName'] = 'efg';

    // send
    var response = await request.send();

    print(response.statusCode);

    // listen for response
    response.stream.transform(utf8.decoder).listen((value) {
      print(value);

    });

1 Comment

When I use your code it gives me error saying "image":["No file was submitted."]. Any ideas on how to solve that ?
6

Please try below solution

Future<String> uploadImageHTTP(file, url) async {

  var request = http.MultipartRequest('POST', Uri.parse(url));
  request.files.add(await http.MultipartFile.fromPath('picture', file.path));
  var res = await request.send();
  return res.reasonPhrase;

}

2 Comments

I got this error. A value of type 'String?' can't be returned from the function 'uploadImageHTTP' because it has a return type of 'Future<String>'.
consider null safety changes
5

Consider using Flutter's Firebase Storage plugin -- it has features that could be useful for uploading large image files on a mobile connection.

I wrote the plugin, contributions and feedback are welcome!

2 Comments

Thanks, I was able to do it with http client library
"Use a Firebase plugin (that I wrote)", is not an answer to "How to upload image in Flutter?".
4

First of all choose your image from gallery or Camera

File _image;
Future _getImage() async {
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
_image = image;
});
}

Now call the below function on button click or inside the _getImage() function. With the file i'm uploading other fields also you see in the saveInAttendance()

Don't forget to import package :

import 'package:dio/dio.dart';
import 'package:path/path.dart';

Future saveInAttendance( BuildContext context,String entryType,String mode) async {
        Dio dio = new Dio();
        FormData formData = new FormData(); // just like JS
        formData.add("inimageFile", new UploadFileInfo(_image, basename(_image.path)));
        formData.add("compID",2);
        formData.add("company_id",2);
        formData.add("EntryType", entryType);
        formData.add("emp_code", 5);
        formData.add("Mode",mode);
        formData.add("location",""+_startLocation.latitude.toString()+"-"+_startLocation.longitude.toString());
        dio.post(url_save_attendance, data: formData, options: Options(
            method: 'POST',
            responseType: ResponseType.json // or ResponseType.JSON
        ))
            .then((r) {
          setState(() {
            var data = json.decode(r.toString());
            if(data["apiMessage"].contains('Saved')){
              warningAlert("Attendance Saved", "Your attendance saved Successfully",context);
            }
          });
        }).catchError(print);
      }

For more Info you can visit Here

Comments

2

to get Body from request Instead of

response.stream.transform(utf8.decoder).listen((value) {
    print(value);
  });

I use:

String body=await response.stream.bytesToString()

Comments

1

my working code below, based on @TejaDroid's sample, it upload one image via the AWS Gateway API with a lambda function behind to store the image into S3.

uploadImageWithhttp(File imageFile, int serialno) async {
    var postBody= {
        'username': '[email protected]',  
        "productid": "1000123",             //TODO
        "imageno": serialno.toString(), 
        'image': imageFile != null ? base64Encode(imageFile.readAsBytesSync()) : '',
    };

    final response = await http.post(
      constAWSAPIGateway_UploadImage[CONST_API_STAGE],
      headers: {
        //AuthUtils.AUTH_HEADER: _authToken
        'Content-Type' : 'application/json',
      },
      body: json.encode(postBody),
    );

    final responseJson = json.decode(response.body);

    print(responseJson);
  }

Comments

1
updateProfile() async {
        try {
          if (_formKey.currentState.validate()) {
            _formKey.currentState.save();
            var dio = new Dio();
            var formData = FormData.fromMap({
              'name': name,
              'con_person_name': concernedPersonName,
              'email': email,
              'phone': phoneNumber,
              'password': password,
              'token': token,
              'user_type': '3',
              'license_no': licenceNumber,
              'gstno': gstNumber,
              'address': address,
              'hospital_id': '102'
              'image': await MultipartFile.fromFile(_image?.path,
            filename: _image.path.split('/').last ?? 'image.jpeg'),
           
            });
            var response = await dio.post('$SERVER_ADDRESS/api/doctorregister',
                data: formData);
            print(response.statusCode);
            print(response.data);
          }
        } catch (error) {
          print(error.toString());
        }
      }

1 Comment

Along with your answer please. provide an explanation
1

I have found a easy way to upload images in flutter and then even receiving it on the server.

Flutter:

 MaterialButton(
                color: Colors.blue,
                child: Text(
                  "Pick Image from Camera",
                  style: TextStyle(
                      color: Colors.white70, fontWeight: FontWeight.bold),
                ),
                onPressed: () async {
                  final XFile? photo =
                      await _picker.pickImage(source: ImageSource.camera);
                  print(photo!.path);
                
                  await uploadImage(photo.path);

                },
              ),  

'uploadImage' function:

uploadImage(String filepath) async {
    var url = 'http://192.168.75.57:4000/upload';
    var request = http.MultipartRequest('POST', Uri.parse(url));
    request.files.add(await http.MultipartFile.fromPath("img", filepath));
    request.fields['_id'] = "abcdef";
    request.headers.addAll({
      "Content-type": "multipart/form-data",
    });
    var response = request.send();
    return response;
  }

On the server Side: (Nodejs) For this, first install multer (npm install multer)

const multer = require('multer');
const path = require('path')

const storage = multer.diskStorage({
    destination: './uploads',
    filename: (req, file, cb) => {
        cb(null, (new Date()).getTime().toString() + ".jpg");
    },
});

const fileFilter = (req, file, cb) => {
    if (file.mimetype == "image/jpeg" || file.mimetype == "image/png") {
        cb(null, true);
    } else {
        cb(null, false);
    }
};

const upload = multer({
    storage: storage,
    limits: {
        fileSize: 1024 * 1024 * 6,
    },
    fileFilter: fileFilter,
});

Finally, honoring the request from flutter application: (In router.js)

router.post('/upload', upload.single("img"), function (req, res) {
    console.log("hit")
    console.log(req.body._id)
    res.send("ok")
})

This method worked for me and I found it comparatively easier than other methods.

Comments

0

Import dio, image_picker library

    Future _onGalleryPressed() async {
            Future<File> image = ImagePicker.pickImage(source: ImageSource.gallery);
            setState(() {
              this._imageFile = image;
            });
            File img = await image;
            Navigator.of(context).pop();
            if (img != null) {
              //API CALL
              try {
                FormData formData = new FormData.from({"file": path});
                var url = backendUrl + "/upload-image";
                var token = await _getMobileToken();
                Map<String, String> headers = {
                  'Authorization': 'Bearer $token',
                  "Content-Type": "multipart/form-data",
                  "X-Requested-With": "XMLHttpRequest"
                };
                await dio.post(url,
                  data: formData,
                  options: Options(
                      method: 'POST',
                      headers: headers,
                      responseType: ResponseType.json // or ResponseType.JSON
                      ));
                Navigator.pop(context);
              } catch (e) {}
            }
          }

1 Comment

How do I receive it in my .php?
0

If you want to upload it as a binary file.

  static uploadFile(File imageFile) async {
    final response = await http.post(postURL, body: imageFile.readAsBytesSync());
    return json.decode(response.body);
  }

Thank you

Comments

0

I have checked about it at multiple places finally i found a solution -

                    var objToSend = {
                          "file": await MultipartFile.fromFile(
                                file.path,
                                filename: filename,
                             ),
                    };

                    FormData formData = FormData.fromMap(objToSend);
                   
                    print(formData.files.toString());
                    Dio dio = new Dio();

                    await dio
                        .post(_toSend,
                            data: formData,
                            options: Options(
                               method: 'POST',
                               headers: <String, String>{
                                  "Content-Type": "application/json",
                                  "Access-Control-Allow-Origin": "*",
                                  "Authorization": 'Bearer ' + token
                                 },
                            ))
                        .whenComplete(() {
                             print('uploaded');
                         }).catchError((onError) {
                             print('failed');
                         });

Comments

0
const express = require('express');
const mongoose = require('mongoose');
const multer = require('multer');
const app = express();
const port = 3000;

// MongoDB connection
mongoose.connect('mongodb://localhost:27017/yourdb', {
  useNewUrlParser: true,
  useUnifiedTopology: true,
}).then(() => {
  console.log('Connected to MongoDB');
}).catch((err) => {
  console.error('MongoDB connection error:', err);
});

// Define Image Schema
const imageSchema = new mongoose.Schema({
  imageData: Buffer,
  contentType: String,
});

const Image = mongoose.model('Image', imageSchema);

// Setup multer storage (store image in memory)
const storage = multer.memoryStorage();
const upload = multer({ storage: storage });

// POST route to upload image
app.post('/upload', upload.single('image'), async (req, res) => {
  try {
    const newImage = new Image({
      imageData: req.file.buffer,
      contentType: req.file.mimetype,
    });

    // Save the image to MongoDB
    await newImage.save();
    res.status(200).send('Image uploaded successfully');
  } catch (error) {
    res.status(500).send('Failed to store image');
  }
});

// Start the server
app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});



import 'dart:io';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:http/http.dart' as http;
import 'package:http_parser/http_parser.dart';

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

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

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

class _ImageUploadPageState extends State<ImageUploadPage> {
  final ImagePicker _picker = ImagePicker();

  // Variable to store picked image
  XFile? _image;

  // Function to pick an image
  Future<void> _pickImage() async {
    final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
    if (image != null) {
      setState(() {
        _image = image;
      });
    }
  }

  // Function to upload image to Node.js server
  Future<void> _uploadImage() async {
    if (_image == null) return;

    final bytes = await _image!.readAsBytes();
    final uri = Uri.parse('http://192.168.1.5:3000/upload'); // Change to your server's local IP

    // Prepare the multipart request
    final request = http.MultipartRequest('POST', uri)
      ..files.add(http.MultipartFile.fromBytes(
        'image',
        bytes,
        filename: 'image.jpg',
        contentType: MediaType('image', 'jpeg'), // Correct mime type for JPEG images
      ));

    try {
      final response = await request.send();
      if (response.statusCode == 200) {
        print('Image uploaded successfully');
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Image uploaded successfully')));
      } else {
        print('Image upload failed: ${response.statusCode}');
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Image upload failed')));
      }
    } catch (e) {
      print('Error: $e');
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Error uploading image')));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Image Upload'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            if (_image != null)
              Image.file(File(_image!.path), height: 200, width: 200),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _pickImage,
              child: Text('Pick Image'),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _uploadImage,
              child: Text('Upload Image'),
            ),
          ],
        ),
      ),
    );
  }
}

1 Comment

There is an answer that has already been upvoted many times by the community. Could you explain how your answer is better? Also, write a few words on how it works.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.