【fw_cow】flutter腾讯cos上传插件ios端的报错修正

936 阅读3分钟

在flutter开发中,我们需要上传腾讯cos来存储文件,但是官方对flutter的支持并不友好,好在有开发者提供了一个插件fw_cos,当前版本为0.0.4,支持Android和ios。此插件在Android表现正常,但在ios有点小问题,而且作者未将此插件开源,无法提交pr,只能自己手动修正。

一、COSXMLService 已存在问题

在ios端上传单文件的时,第一次可以上传成功,但是第二次则报如下错误。

集成 SDK 后抛出异常 默认的 COSXMLService 已存在,如有新的配置,请通过 registerCOSXMLWithConfiguration:withKey:重新注册

此问题在官网文档常见错误已经给出答案:在 SDK 中,不同的 COSXMLService 实例对应不同的配置(配置信息可以参考相关属性),例如 regionName 为 ap-guangzhou 和 ap-beijing 是两个不同的配置,需要注册两个不同的 service,如果在用 ap-guangzhou 注册了一个 service 之后,将其 region 又改成 ap-beijing(官方这里还是ap-guangzhou,可能是笔误), 重新注册就会触发该异常。

  • 通过xocde编辑器打开项目,在Pods中找到插件fw_cow的源码位置。

image.png

  • 找到[QCloudCOSXMLService registerDefaultCOSXMLWithConfiguration:configuration]这一行,并把他注释掉,替换的内容如下所示。
if(![QCloudCOSXMLService hasServiceForKey: region]){
  [QCloudCOSXMLService registerCOSXMLWithConfiguration:configuration withKey: region];
}

// [QCloudCOSXMLService registerDefaultCOSXMLWithConfiguration:configuration];

二、多图片上传问题

上传图片是用FwCos.uploadByFile方法,当一张一张图片上传的时候,结果都是都会通过invokeMethod方式,原生调用flutter层的方式来传递结果,当需要传下一张图片的时候再次调用此方法就好。但当我们需要上传多张图片的时候,需要使用await Future.forEach来多次调用。不过这样会出现上传一张成功后,就无法继续运行,后面的方法都不会调用。

void _upLoadTxCos() async {
    // imglist 为本地图片列表
    await Future.forEach(imgList, (Img e) async {
      String absPath = e.file.path;
      var cosPath = 'source/${e.name}';
      await FwCos.uploadByFile(
        ['region'],
        ['appid'],
        ['bucket'],
        ['tmpSecretId'],
        ['tmpSecretKey'],
        ['sessionToken'],
        ['expiredTime'],
        cosPath // cos上的路径,
        absPath // 本地文件路径
      );
    });

    print('上传完成');
}

一般这种情况就是一个async方法无返回值,所以后面的await就会一直等待。

通过查看源码发现,在方法调用完成setFinishBlock的方法中,调用的是invokeMethod方法,而没有result,所以await FwCos.uploadByFile永远不会有返回值,也无法进行下一步。

只需要在成功的方法中使用result将返回值回调,flutter中就可以正常运行了。

[put setFinishBlock:^(id outputObject, NSError* error) {
  NSMutableDictionary *data = [NSMutableDictionary dictionary];
  [data setValue:urlstr forKey:@"localPath" ];
  [data setValue:cosPath forKey:@"cosPath"];
  if(error.code == 0){
      // 添加这一句
      result(@{@"localPath": urlstr, @"cosPath": cosPath});
      
      [self.channel invokeMethod:@"onSuccess" arguments:data];
  }else{
      [data setValue: error.domain forKey:@"message"];
      [self.channel invokeMethod:@"onFailed" arguments:data];
  }
}];

三、总结

很多第三方库,官方对flutter不友好就很蛋疼,也有很多开发者帮官方做了适配,但毕竟是用爱发电,不是那么完善,好在flutter中对插件的源码修改特别方便,这时候就需要发挥自己创意了。

这次用到腾讯cos上传功能,就遇到点小问题,花了不少时间找原因在哪。如果大家也用到这个插件,可以通过上面的方法将ios端的问题修正一下。