flutter开发实战-文件上传及上传队列

flutter开发实战-文件上传及上传队列

之前开发中遇到了发帖子图片上传,上传到七牛。

一、实现Dio上传

上传使用到Dio上传功能,具体代码

dart 复制代码
// 上传文件(图片)
  doUploadFile(String url, UploadFileInfo fileInfo,
      {Map<String, dynamic>? params,
      OnUploaded? uploaded,
      OnFailure? failure}) async {
    try {
      String timeStamp = DateTime.now().millisecondsSinceEpoch.toString();
      Map<String, dynamic> fromParams = Map();
      if (params != null && params.isNotEmpty) {
        fromParams.addAll(params);
      }

      fromParams["file"] = await MultipartFile.fromFile(fileInfo.file.path,
          filename: '${fileInfo.key}-${timeStamp}.jpg');

      FormData formData = FormData.fromMap(fromParams);
      Response? response = await dio.post(url, data: formData);
      assert(() {
        // assert只会在debug模式下执行,release模式下不会执行
        // 打印信息
        LoggerManager().error('''api: $url\nresult: $response''');
        return true;
      }());

      if (response != null) {
        Map<String, dynamic> result = json.decode(response.toString());
        assert(() {
          // assert只会在debug模式下执行,release模式下不会执行
          // 打印信息
          LoggerManager().debug('''api: $url\nresult: $result''');
          return true;
        }());

        if (response.statusCode == 200) {
          if (uploaded != null) {
            uploaded(result);
          }
        } else {
          //返回失败信息
          LoggerManager().error('''api: $url\nresult: $result''');

          ApiHttpError apiHttpError =
              ApiHttpError(ApiHttpErrorType.Default, "请求失败!");

          if (failure != null) {
            failure(apiHttpError);
          }
        }
      } else {
        //返回失败信息
        // 没有获得response,failure
        ApiHttpError apiHttpError =
            ApiHttpError(ApiHttpErrorType.Default, "请求失败!");

        if (failure != null) {
          failure(apiHttpError);
        }
      }
    } on DioError catch (e, s) {
      // catch到异常,failure
      LoggerManager().error("doUploadFile api: $url, dioError:$e, s:$s");
      ApiHttpError apiHttpError = getRequestFailure(e.response, e.type);

      if (failure != null) {
        failure(apiHttpError);
      }
    } catch (e) {
      // 可以捕获任意异常
      ApiHttpError apiHttpError =
          ApiHttpError(ApiHttpErrorType.Default, "${e.toString()}");

      if (failure != null) {
        failure(apiHttpError);
      }
    }
  }

二、实现上传到七牛uploader_tool

上传七牛需要获取上传七牛的token

dart 复制代码
void getQiniuToken(
      {required Function(String token) completion,
      required Function(ApiHttpError) failure}) {
    QiniuTokenRequest request = QiniuTokenRequest();
    GApiRepository.getQiniuToken(
      request: request,
      success: (response) async {
        Map<String, dynamic>? object = response.object;
        String token = "";
        if (object != null && object.isNotEmpty) {
          token = object["uptoken"];
        }

        if (completion != null) {
          completion(token);
        }
      },
      failure: (error) {
        if (failure != null) {
          failure(error);
        }
      },
    );
  }

调用doUploadFile实现上传

dart 复制代码
const String kQiniuUpHost = "http://up.qiniu.com";
const String kQiniuUndefinedKey = "?";
const String kQiniuUserAgent = "qiniu-ios-sdk";

const String kBucket = "bucket";
const String kQiniuDomainPreUrl = "domain";


void uploadImage(String imagePath, String token, {required Function(String key) completion,
    required Function(ApiHttpError) failure}) {
    String? key = StringUtils.toMD5(imagePath);
    String random = StringUtils.getRandom(10);
    String imageKey = "${key}-${random}";

    Map<String, dynamic> params = Map();
    params["bucket"] = "avatar";
    params["x:id"] = imageKey;
    params["token"] = token;
    params["User-Agent"] = kQiniuUserAgent;

    UploadFileInfo fileInfo =
    UploadFileInfo(file: File(imagePath), key: imageKey);

    HttpApi().doUploadFile(
      kQiniuUpHost,
      fileInfo,
      params: params,
      uploaded: (Map<String, dynamic> result) {
        String? aResultKey = result["key"];
        completion(aResultKey ?? "");
      },
      failure: (ApiHttpError error) {
        failure(error);
      },
    );
  }

三、实现上传队列

简单实现上传队列,这里上传采用一个接着一个上传,

代码如下

dart 复制代码
class UploaderQueue {

  // imagePath - key
  Function(Map<String, String> keys)? completion;

  Function(ApiHttpError error)? failure;

  UploaderQueue({
    this.completion,
    this.failure,
  });

  // 是否有任务正在进行时
  bool _isUploading = false;

  // 任务列表
  final List<String> _imagePathList = [];

  // 上传的keys
  final Map<String, String> _keyMap = {};

  // 上传的服务
  final UploaderTool _uploaderService = UploaderTool();

  void addImagePaths(List<String> imagePaths) {
    if (_isUploading) {
      return;
    }
    _imagePathList.addAll(imagePaths);
  }

  void doUpload() {
    if (_imagePathList.isEmpty) {
      return;
    }

    if (_isUploading) {
      return;
    }

    _isUploading = true;
    // 获取当前上传的图片ImagePath
    String imagePath = _imagePathList[0];

    _uploaderService.uploaderImage(imagePath, completion: (String key) {
      if (key.isNotEmpty) {
        _keyMap[imagePath] = key;
      }

      // 出队列
      _imagePathList.removeAt(0);
      _isUploading = false;

      if (_imagePathList.isNotEmpty) {
        // 不为空的时候
        doUpload();
      } else {
        if (completion != null) {
          completion!(_keyMap);
        }
      }
    }, failure: (ApiHttpError error) {
      cancel();
      if (failure != null) {
        failure!(error);
      }
    });
  }

  void cancel() {
    _isUploading = false;
    _imagePathList.clear();
  }

  void clear() {
    _isUploading = false;
    _imagePathList.clear();
  }
}

四、小结

flutter开发实战-文件上传及上传队列,获取token,上传图片到七牛。

学习记录,每天不停进步。

相关推荐
昔人'1 天前
css`text-wrap:pretty`
前端·css
勇敢di牛牛1 天前
Vue+mockjs+Axios 案例实践
前端·javascript·vue.js
詩句☾⋆᭄南笙1 天前
HTML列表、表格和表单
服务器·前端·html·表格·列表·表单
IT_陈寒1 天前
Python性能翻倍的5个冷门技巧:从GIL逃逸到内存视图的实战优化指南
前端·人工智能·后端
南城巷陌1 天前
错误边界:用componentDidCatch筑起React崩溃防火墙
前端·react.js·前端框架
FinClip1 天前
OpenAI推出Apps SDK,你的企业App跟上了吗?
前端·app·openai
馨谙1 天前
Linux中的管道与重定向:深入理解两者的本质区别
前端·chrome
黄林晴1 天前
Kotlin 2.3.0-Beta1 重磅发布:这些新特性让代码更安全、更高效!
android·kotlin
2501_915921431 天前
iOS 应用加固与苹果软件混淆全解析 IPA 文件防反编译、混淆加密与无源码加固策略
android·macos·ios·小程序·uni-app·cocoa·iphone
夏天想1 天前
复制了一个vue的项目然后再这个基础上修改。可是通过npm run dev运行之前的老项目,发现运行的竟然是拷贝后的项目。为什么会这样?
前端·vue.js·npm