Flutter DIO:使用带有 Dio 包的二进制体上传图像

Posted

技术标签:

【中文标题】Flutter DIO:使用带有 Dio 包的二进制体上传图像【英文标题】:Flutter DIO: upload image using binary body with Dio package 【发布时间】:2020-10-20 06:01:51 【问题描述】:

使用 http 包,我可以通过将二进制数据放入 post 调用的正文中,就像在这段代码的 sn-p 中一样,将图像发送到服务器:

var response = await http.post('My_url', body: File(path).readAsBytesSync(),  headers: 
                    'apikey': 'myAPIKEY',
                    'Content-Type': 'image/*', // set content-length
                  );

我不能用 Dio 做同样的事情,我不知道如何直接将二进制数据放入正文中(就像我可以用 postman 一样)

【问题讨论】:

你找到解决办法了吗? 还没有,我会尝试写信给 Dio 开发者。 您找到解决方案了吗?遇到同样的问题, 【参考方案1】:

Anirban Das 解决方案正在运行,但是当我尝试上传 24MB 的照片文件时它崩溃可能是由于

Stream.fromIterable(image.map((e) => [e]))

所以我尝试直接将文件作为流读取 file.OpenRead() => 返回Strea<List<in>>>

重音与否,但上传速度也提高了(也许是因为当 你映射 e => [e] 它正在减慢发送数据的速度)但谁知道也许我错了

所以我的最终代码是

Uint8List image = File(path).readAsBytesSync();

Options options = Options(
  contentType: lookupMimeType(path),
  headers: 
    'Accept': "*/*",
    'Content-Length': image.length,
    'Connection': 'keep-alive',
    'User-Agent': 'ClinicPlush'
  
);

Response response = await dio.put(
  url,
  data: file.openRead(), <--- change here
  options: options
);

【讨论】:

【参考方案2】:

我也遇到了和你一样的情况。在 DIO 中,您必须通过流发送二进制数据。这是我如何实现它的示例,

Uint8List image = File(path).readAsBytesSync();

Options options = Options(
  contentType: lookupMimeType(path),
  headers: 
    'Accept': "*/*",
    'Content-Length': image.length,
    'Connection': 'keep-alive',
    'User-Agent': 'ClinicPlush'
  
);

Response response = await dio.put(
  url,
  data: Stream.fromIterable(image.map((e) => [e])),
  options: options
);

【讨论】:

我将添加使用 lookupMimeType() 方法您需要导入 mime 包:import 'package:mime/mime.dart'; 为我工作,但是当我尝试上传 24 MB 的图像时,它可能由于 Stream.fromIterable(image.map((e) => [e]))而崩溃【参考方案3】:

使用 dio 包将二进制数据上传到谷歌存储 api 时,我不断收到 http 403。我能够使用以下方法解决此问题:

      Response responseGoogleStorage = await dio.put(
      googleStorage.url,
      data: File(_imageFile.path).readAsBytesSync(),
      options: Options(
        headers: 
          'Content-Type': contentType,
          'Accept': "*/*",
          'Content-Length': File(_imageFile.path).lengthSync().toString(),
          'Connection': 'keep-alive',
        ,
      ),
    );

【讨论】:

非常感谢!这节省了一天!并不是真的想只为一个请求使用好的旧 http!与您相同的场景,将数据上传到 Google 存储并获得 403 响应。【参考方案4】:

如果有人偶然发现同样的问题,请提出我的解决方案。

我必须在已签名的 google 存储 URL 上上传文件。在 PUT 请求正文中插入文件二进制数据所需的 API。使用 DIO 插件无法实现,我使用 DART HTTP 包解决了这个问题,下面是示例代码。

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

await http.put(
  Uri.parse(uploadURL),
  headers: 
    'Content-Type': mimeType,
    'Accept': "*/*",
    'Content-Length': File(filePath).lengthSync().toString(),
    'Connection': 'keep-alive',
  ,
  body: File(filePath).readAsBytesSync(),
);

【讨论】:

这拯救了一天!不知道为什么 DIO 很难处理这个问题,但是好的 ol fashion dart http 可以处理它。 DIO 确实进行了上传,但只推送了字节数组,这没有帮助。谢谢!【参考方案5】:

我已经声明了一个名为“数据”的 FormData 对象,并有一个图像映射,其中键为文件名,值作为文件路径。 'image' 是在服务器端定义的键。

 data.files.add(MapEntry(
    'image',
      await MultipartFile.fromFile(image.values.first, filename: "$image.values.first.split("/").last")
                                ));

【讨论】:

以上是关于Flutter DIO:使用带有 Dio 包的二进制体上传图像的主要内容,如果未能解决你的问题,请参考以下文章

使用 Dio/bloc Flutter 处理错误

如何将函数中的参数用于带有 Dio 包的 http 请求正文

flutter中的dio包如何在这段代码中加入base-url和url和apikey

Flutter Dio源码分析--Dio介绍

flutter中dio网络get请求使用总结

Flutter进行HTTP请求并保存登陆状态(dio)