如何在Dart/Flutter中向API发送图片?

19

我看到了其他的类似问题,但那并不是我想要的,我不想将图片上传到服务器,也不想转换为base64...

我只想以表单数据或其他方式发布文件,并获得返回的信息。

我有这个代码,但它没有起作用:

  void onTakePictureButtonPressed() {
    takePicture().then((String filePath) {
      if (mounted) {
        setState(() {
          imagePath = filePath;
          videoController?.dispose();
          videoController = null;
        });

        http.post('http://ip:8082/composer/predict', headers: {
          "Content-type": "multipart/form-data",
        }, body: {
          "image": filePath,
        }).then((response) {
          print("Response status: ${response.statusCode}");
          print("Response body: ${response.body}");
        });


        if (filePath != null) showInSnackBar('Picture saved to $filePath');
      }
    });
  }
4个回答

42

最简单的方法是像这篇帖子中那样发布一个多部分请求,然后将其发送到服务器。

确保在文件开头导入以下内容:

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

在你的代码中任意添加这个类:

upload(File imageFile) async {    
      // open a bytestream
      var stream = new http.ByteStream(DelegatingStream.typed(imageFile.openRead()));
      // get file length
      var length = await imageFile.length();

      // string to uri
      var uri = Uri.parse("http://ip:8082/composer/predict");

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

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

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

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

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

然后使用以下方式上传:

upload(File(filePath));

在你的代码中:

void onTakePictureButtonPressed() {
    takePicture().then((String filePath) {
      if (mounted) {
        setState(() {
          imagePath = filePath;
          videoController?.dispose();
          videoController = null;
        });

       // initiate file upload
       Upload(File(filePath));

        if (filePath != null) showInSnackBar('Picture saved to $filePath');
      }
    });
  }

1
我给我发布的代码写了一些注释。基本上它打开并将文件读入字节流,将其添加到多部分请求中,然后作为POST请求发送。您所要做的就是在代码中的某个地方包含此类并调用它。 - Bostrot
1
@MetaCode,你需要导入包import 'package:async/async.dart';而不是import 'dart:async';。还有这个:import 'dart:convert'; - Bostrot
好的,你可以/应该用小写字母来命名它:upload(...) 而不是 Upload(...)。请参见编辑后的帖子。 - Bostrot
我想在我的MultipartRequest中添加一个字段,如 request.fields['name'] = DateTime.now().toIso8601String(); 但是,每次都会出现错误。但是,如果我给它一个静态值,如 request.fields['name'] = "test.png" 就可以工作。有人能告诉我我做错了什么吗? - Jay Mungara
如何将文件作为二进制发送 - Pratik Butani
显示剩余2条评论

4
 import 'package:dio/dio.dart'; //From 3.x.x version

    uploadImage(){
        var formData = FormData();
        formData.files.add(MapEntry("Picture", await MultipartFile.fromFile(data.foto.path, filename: "pic-name.png"), ));
        var response = await dio.client.post('v1/post', data: formdata);
    }

1
一个小提示:当向Spring Boot应用程序发送文件数组时(不需要类似“pictures []”的东西),我发现按照这里的说明很有用:https://github.com/flutterchina/dio#multiple-files-upload - 阅读如果您不想要“[]” - funder7

3
如果您要将图像发送到 PHP Laravel 服务器,请在将其发送到服务器时尝试减小图像的大小。我使用了“Image Picker”包来减小图像的大小。Image Picker
var image = await ImagePicker.pickImage(source: imageSource, imageQuality: 50, maxHeight: 500.0, maxWidth: 500.0);

然后,使用该图像创建一个多部分文件,将其添加到表单数据中,并使用dio库将表单数据发送到服务器上的post请求。有关发送数据的详细信息,请参见@Elialber Lopes的答案。

这对我有用。


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

Future<void> sendImage(String apiUrl, String imagePath) async {
  // Convert image to bytes
  var bytes = await rootBundle.load(imagePath);
  var buffer = bytes.buffer;
  var imageBytes = buffer.asUint8List(bytes.offsetInBytes, bytes.lengthInBytes);

  // Encode the bytes
  var base64Image = base64Encode(imageBytes);

  // Send the API request
  var response = await http.post(apiUrl, body: {
    'image': base64Image,
  });

  // Handle the API response
  if (response.statusCode == 200) {
    // Success
  } else {
    // Error
  }
}

在这个例子中,apiUrl参数是API端点的URL,而imagePath参数是设备上图像文件的路径。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接