flutter 使用dio如何上传图片等资源至七牛云

3,853 阅读4分钟

       最近闲来无事又重拾起了flutter之旅(ps: 码农就是这么的贱,没事喜欢找事),哈哈,上述只针对我自己,向广大码农道歉,别给我发律师函哦。        背景:n年前,初学node的时候搭建了一个漏洞百出的后台接口系统,又不想去重写,只能能用就用,写到一半发现,算了,倔强个什么劲呢,直接用别人现成的接口算了,不是有个大大大佬,把微博用flutter重构了,真的是牛逼至极(ps: 奈何本人没文化,一句牛逼走天下),我也去翻翻我手头的接口,发现还真有。

首先:七牛云的地址是和普通的接口请求是不一样的,所以需要重新new一个新的dio实例,如:

// 上传七牛云服务
class UploadAxios {
  Dio uploadDio;
  UploadAxios() {
    uploadDio = Dio(BaseOptions(
      baseUrl: 'https://up-z2.qiniup.com', // 这里的地址得看你们的七牛云服务器在哪里,一一对应就好了
      connectTimeout: 5000000,
      receiveTimeout: 10000000,
    ));
  }

  // post
  dynamic post(String url, [dynamic params]) async {
    try {
      Response response = await uploadDio.post(url, data: params);
      return response.data;
    } catch (e) {
      return;
    }
  }

  // 并发
  Future<List<dynamic>> all(Iterable<Future> list) async {
    return await Future.wait(list);
  }
}

final UploadAxios uploadAxios = UploadAxios();

所谓遇事不决写dynamic,没有什么是一个dynamic解决不了的问题,如果有那就写一个屏幕。哈哈,这是个坏习惯,如果时间不是很紧急的话,还是要把这些类型都推导表明一下,养成一个良好的习惯,毕竟dart是强类型语言,可不是写js了,anyscript表示,我也可以遇事不决写any。

其次:就开始封装我们的上传资源通用方法了,上传七牛云之前要先通关后台向七牛云获取token,单次token只对单次上传任务有效。

dio单文件上传

单文件上传的话就需要用到Future.wait了,由于我这边接口的特定性,所以采用了单文件上传方式,一般可以用dio文档的多文件上传就可以了。

Future<List<dynamic>> Function(List<String>) uploadQiNiu =
    (List<String> paths) async {
  // 获取上传七牛云token
  final publicsModal.QiNiuTokenResponse tokenR =
      await publics.api.getQiNiuToken();
  if (tokenR.code != 1) return [];
  final List<dynamic> response = await uploadQiNiuFiles(paths, tokenR);
  if (response == null) return [];
  // 构造成可储存的数据结构
  return formatSource(tokenR.data.domain, response);
};
// 并发上传七牛云
Future<List<dynamic>> Function(List<String>, publicsModal.QiNiuTokenResponse)
    uploadQiNiuFiles =
    (List<String> paths, publicsModal.QiNiuTokenResponse tokenR) async {
  return uploadAxios
      .all(paths.map((e) async => uploadQiNiuFile(e, tokenR)).toList());
};
// 单个上传七牛云
Future<dynamic> Function(String, publicsModal.QiNiuTokenResponse)
    uploadQiNiuFile =
    (String path, publicsModal.QiNiuTokenResponse tokenR) async {
  final String token = tokenR.data.token;
  final String basePath = tokenR.data.basePath;
  // 生成随机数文件名
  String name = Random().nextInt(10000).toString() +
      DateTime.now().millisecondsSinceEpoch.toString() +
      path.substring(path.lastIndexOf("."));
  // 构造FormData 
  FormData formData = FormData.fromMap({
    "file": await MultipartFile.fromFile(path, filename: name),
    'token': token, // 上传前,向七牛云获取到的token
    'key': '$basePath$name' // 这个是我们加传的,所以采用单文件上传
  });
  // 开始上传
  return uploadAxios.post('', formData);
};
上传多个文件

只需要把上面的并发去掉,把file字段改成files就可以了,如:

FormData.fromMap({
    "name": "wendux",
    "age": 25,
    "file": await MultipartFile.fromFile("./text.txt",filename: "upload.txt"),
    "files": [
      await MultipartFile.fromFile("./text1.txt", filename: "text1.txt"),
      await MultipartFile.fromFile("./text2.txt", filename: "text2.txt"),
    ]
 });
response = await dio.post("/info", data: formData);

具体请参考dio文档

好了就是这么的简单,到这里差不多就大功告成了,给自己鼓个掌。 项目地址:传送门

目前实现了一套完整的社交平台的逻辑,项目介绍先写到这里,有其他问题的小伙伴,欢迎评论区留言,知无不言。

                                                                                                                                                   撒花                                                                                                                                                    完结