美文网首页
flutter直接上传文件到阿里云oss

flutter直接上传文件到阿里云oss

作者: 阳春boy | 来源:发表于2020-12-29 14:24 被阅读0次

    需求

    上传视频到oss,之前是走后端上传到oss,会有一个问题就是我要先上传给后端,后端再上传给oss就会导致上传多次,消耗时间过长影响用户体验,所以我参考文档写了直接上传到阿里云oss获取到文件访问路径。

    代码实现

    以下是我写的一个上传oss的类,只需要替换ossAccessKeyId, ossAccessKeySecret, bucket, url, expiration这几个参数就可以直接实现上传

    import 'dart:convert';
    import 'dart:io';
    import 'dart:math';
    import 'package:crypto/crypto.dart';
    import 'package:dio/dio.dart';
    
    class UploadOss {
    
      static String ossAccessKeyId = 'ossAccessKeyId';
    
      static String ossAccessKeySecret = 'ossAccessKeySecret';
      // oss设置的bucket的名字
      static String bucket = 'bucketName';
      // 发送请求的url,根据你自己设置的是哪个城市的
      static String url = 'https://$bucket.oss-cn-hangzhou.aliyuncs.com';
    
      // 过期时间
      static String expiration = '2025-01-01T12:00:00.000Z';
    
      /**
       * @params file 要上传的文件对象
       * @params rootDir 阿里云oss设置的根目录文件夹名字
       * @param fileType 文件类型例如jpg,mp4等
       * @param callback 回调函数我这里用于传cancelToken,方便后期关闭请求
       * @param onSendProgress 上传的进度事件
       */
    
      static Future<String> upload({ File file , String rootDir = 'moment', String fileType, Function callback, Function onSendProgress}) async {
        String policyText = '{"expiration": "$expiration","conditions": [{"bucket": "$bucket" },["content-length-range", 0, 1048576000]]}';
    
        // 获取签名
        String signature = getSignature(policyText);
    
        BaseOptions options = new BaseOptions();
        options.responseType = ResponseType.plain;
    
        //创建dio对象
        Dio dio = new Dio(options);
        // 生成oss的路径和文件名我这里目前设置的是moment/20201229/test.mp4
        String pathName = '$rootDir/${getDate()}/${getRandom(12)}.${fileType == null ? getFileType(file.path) : fileType}';
    
        // 请求参数的form对象
        FormData data = new FormData.fromMap({
          'key': pathName,
          'policy': getSplicyBase64(policyText),
          'OSSAccessKeyId': ossAccessKeyId,
          'success_action_status': '200', //让服务端返回200,不然,默认会返回204
          'signature': signature,
          'contentType': 'multipart/form-data',
          'file': MultipartFile.fromFileSync(file.path),
        });
    
        Response response;
        CancelToken uploadCancelToken = CancelToken();
        callback ?? callback(uploadCancelToken);
    
        try {
          // 发送请求
          response = await dio.post(url, data: data, cancelToken: uploadCancelToken, onSendProgress: (int count, int data) {
            onSendProgress(count, data);
          });
          // 成功后返回文件访问路径
          return '$url/$pathName';
        } catch(e) {
          throw(e.message);
        }
    
      }
    
    
      /*
      * 生成固定长度的随机字符串
      * */
      static String getRandom(int num) {
        String alphabet = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM';
        String left = '';
        for (var i = 0; i < num; i++) {
    //    right = right + (min + (Random().nextInt(max - min))).toString();
          left = left + alphabet[Random().nextInt(alphabet.length)];
        }
        return left;
      }
      /*
      * 根据图片本地路径获取图片名称
      * */
      static String getImageNameByPath(String filePath) {
        // ignore: null_aware_before_operator
        return filePath?.substring(filePath?.lastIndexOf("/")+1,filePath?.length);
      }
      /**
       * 获取文件类型
       */
      static String getFileType(String path) {
        print(path);
        List<String> array = path.split('.');
        return array[array.length -1];
      }
      /// 获取日期
      static String getDate() {
        DateTime now = DateTime.now();
        return '${now.year}${now.month}${now.day}';
      }
    
      // 获取plice的base64
      static getSplicyBase64(String policyText) {
        //进行utf8编码
        List<int> policyText_utf8 = utf8.encode(policyText);
        //进行base64编码
        String policy_base64 = base64.encode(policyText_utf8);
        return policy_base64;
      }
    
      /// 获取签名
      static String getSignature(String policyText) {
        //进行utf8编码
        List<int> policyText_utf8 = utf8.encode(policyText);
        //进行base64编码
        String policy_base64 = base64.encode(policyText_utf8);
        //再次进行utf8编码
        List<int> policy = utf8.encode(policy_base64);
        //进行utf8 编码
        List<int> key = utf8.encode(ossAccessKeySecret);
        //通过hmac,使用sha1进行加密
        List<int> signature_pre = Hmac(sha1, key).convert(policy).bytes;
        //最后一步,将上述所得进行base64 编码
        String signature = base64.encode(signature_pre);
        return signature;
      }
    }
    
    

    调用上传的例子

    其他参事自己根据自己情况上传

    Future<String> uploadFile(File file, { Function onSendProgress, Function callback}) async {
      final String url = await UploadOss.upload(file: file, onSendProgress: onSendProgress, callback: callback);
      return url;
    }
    

    参考文档

    部分内容参考https://blog.csdn.net/yj909364/article/details/105415305

    相关文章

      网友评论

          本文标题:flutter直接上传文件到阿里云oss

          本文链接:https://www.haomeiwen.com/subject/zgjfoktx.html