Flutter中如何上传图片到服务器?

问题描述 投票:0回答:16

我想上传图片,我正在使用 http.Client() 来发出请求,

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: )
}

请求的正文和编码部分应该是什么?

flutter dart file-upload multipartform-data multipart
16个回答
68
投票

使用 MultipartRequest

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);
      });
    }

名称空间:

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

31
投票

最简单的方法是使用http库,

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);
}

12
投票

submitForm()
方法检查身体。

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);
}

10
投票

我已经尝试了以上所有方法,但没有一个可以让我将文件上传到服务器。

经过深入搜索,我得到了一个和Dio一样的插件。

以下代码将文件上传到服务器。

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}");
  }

7
投票

我找到了一个不使用任何外部插件的工作示例,这个 只用

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

代码

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);

    });

6
投票

请尝试以下解决方案

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;

}

5
投票

考虑使用 Flutter 的 Firebase Storage 插件——它具有可用于在移动连接上上传大型图像文件的功能。

我写了这个插件,欢迎贡献和反馈!


4
投票

首先从图库或相机中选择您的图像

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

现在在按钮单击时或在 _getImage() 函数内调用以下函数。通过该文件,我上传了其他字段,您也可以在 saveInAttendance() 中看到

不要忘记导入包:

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);
      }

欲了解更多信息,您可以访问这里


2
投票

从请求中获取正文而不是

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

我用:

String body=await response.stream.bytesToString()

1
投票

我的工作代码如下,基于 @TejaDroid 的示例, 它通过 AWS Gateway API 上传一张图像,并使用后面的 lambda 函数将图像存储到 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);
  }

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
投票

我找到了一种简单的方法来在 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(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;
  }

在服务器端:(Nodejs) 为此,首先安装 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,
});

最后,满足flutter应用程序的请求: (在 router.js 中)

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

这个方法对我来说很有效,而且我发现它比其他方法更容易。


0
投票

导入dio,

image_picker

    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) {}
            }
          }

0
投票

如果您想将其作为二进制文件上传。

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

谢谢你


0
投票

我查了很多地方终于找到了解决方案 -

                    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');
                         });

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'),
            ),
          ],
        ),
      ),
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.