代码实现

以下是我写的一个上传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;
}

另一种方法

目前阿里没有针对Flutter有官方SDK可集成, 但是有人对Flutter的上传有封装库https://pub.dev/packages/aly_oss#-example-tab-, 所以我们只能通过post提交PostObject的形式来上传;

准备工作:

1、获取OSS凭证地址(your oss_sts_server), 通知get直接获取static String ossServerUrl = 'http://.../sts-server/sts.php';

2、上传的存储地址(桶名):static String ossEndPointCdn = '<your endpointcdn>';

// 通过ossServerUrl直接get获取到如下数据
{
        "StatusCode": 200,
          "AccessKeyId": "STS.NSsrKZes4cqm.....",
          "AccessKeySecret": "7eGnLZaEFsRCGYJAnrtdE9n.....",
          "Expiration": "2020-04-08T03:44:21Z",
          "SecurityToken": "CAISlQJ1q6Ft5B2y....."
  }
 
//表单需要的参数: AccessKeyId、AccessKeySecret、SecurityToken;
FormData formdata = new FormData.from({
        //文件名,随意
        'Filename': OssUtil.instance.getImageName(filePath),
        //"可以填写文件夹名(对应于oss服务中的文件夹)/"   fileName
        'key': uploadName,//上传后的文件名
        'policy': OssUtil.policy,
        //Bucket 拥有者的AccessKeyId。
        'OSSAccessKeyId': data['AccessKeyId'],
        //让服务端返回200,不然,默认会返回204
        'success_action_status': '200',
        'signature': OssUtil.instance.getSignature(data['AccessKeySecret']),
        //临时用户授权时必须,需要携带后台返回的security-token
        'x-oss-security-token': data['SecurityToken'],
        'file': new UploadFileInfo(
            file, OssUtil.instance.getImageNameByPath(filePath))
        //必须放在参数最后
   });
//然后通过存储地址直接把表单(formdata)上传上去;
Dio dio=Dio();
dio.options.responseType=ResponseType.plain;
Response response=awaitdio.post(<ossEndPointCdn>,data:formData);
......

tips: 上传成功后图片地址 imageUrl = ossEndPointCdn '/' uploadName;

给一个工具类

import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'dart:math';
 
class OssUtil {
 获取
  //验证文本域
  static String _policyText =
      '{"expiration": "2069-05-22T03:15:00.000Z","conditions": [["content-length-range", 0, 1048576000]]}';//UTC时间 8=北京时间
 
  //进行utf8编码
  // ignore: non_constant_identifier_names
  static List<int> _policyText_utf8 = utf8.encode(_policyText);
  //进行base64编码
  static String policy= base64.encode(_policyText_utf8);
 
  //再次进行utf8编码
  // ignore: non_constant_identifier_names
  static List<int> _policy_utf8 = utf8.encode(policy);
 
  // 工厂模式
  factory OssUtil() => _getInstance();
 
  static OssUtil get instance => _getInstance();
  static OssUtil _instance;
 
  OssUtil._internal();
 
  static OssUtil _getInstance() {
    if (_instance == null) {
      _instance = new OssUtil._internal();
    }
    return _instance;
  }
 
  /*
  *获取signature签名参数
  */
  String getSignature(String _accessKeySecret){
    //进行utf8 编码
    // ignore: non_constant_identifier_names
    List<int> AccessKeySecretUtf8 = utf8.encode(_accessKeySecret);
    //通过hmac,使用sha1进行加密
    List<int> signaturePre = new Hmac(sha1, AccessKeySecretUtf8).convert(_policy_utf8).bytes;
    //最后一步,将上述所得进行base64 编码
    String signature = base64.encode(signaturePre);
    return signature;
  }
 
  // ignore: slash_for_doc_comments
  /**
   * 生成上传上传图片的名称 ,获得的格式:photo/20171027175940_oCiobK
   * 可以定义上传的路径uploadPath(Oss中保存文件夹的名称)
   * @param uploadPath 上传的路径 如:/photo
   * @return photo/20171027175940_oCiobK
   */
  String getImageUploadName(String uploadPath,String filePath) {
    String imageMame = "";
    var timestamp = new DateTime.now().millisecondsSinceEpoch;
    imageMame =timestamp.toString() "_" getRandom(6);
    if(uploadPath!=null&&uploadPath.isNotEmpty){
      imageMame=uploadPath "/" imageMame;
    }
    String imageType=filePath?.substring(filePath?.lastIndexOf("."),filePath?.length);
    return imageMame imageType;
  }
 
  String getImageName(String filePath) {
    String imageMame = "";
    var timestamp = new DateTime.now().millisecondsSinceEpoch;
    imageMame =timestamp.toString() "_" getRandom(6);
    String imageType=filePath?.substring(filePath?.lastIndexOf("."),filePath?.length);
    return imageMame imageType;
  }
 
  /*
  * 生成固定长度的随机字符串
  * */
  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;
  }
 
  /*
  * 根据图片本地路径获取图片名称
  * */
  String getImageNameByPath(String filePath) {
    // ignore: null_aware_before_operator
    return filePath?.substring(filePath?.lastIndexOf("/") 1,filePath?.length);
  }
}

以上就是flutter直接上传文件到阿里云oss的实现步骤的详细内容,更多关于flutter 上传文件到阿里云oss的资料请关注Devmax其它相关文章!

flutter直接上传文件到阿里云oss的更多相关文章

  1. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  2. Flutter中文教程-Cookbook

    Flutter中文网的Cookbook中包含了在编写Flutter应用程序时常见问题及示例。设计基础使用主题共享颜色和字体样式Images显示来自网上的图片用占位符淡入图片使用缓存图Lists创建一个基本list创建一个水平list使用长列表创建不同类型子项的List创建一个gridList处理手势处理点击添加Material触摸水波效果实现滑动关闭导航导航到新页面并返回给新页面传值从新页面返回数据给上一个页面网络从网上获取数据进行认证请求使用WebSockets

  3. android-studio – 未配置Dart SDK

    Initializinggradle…

  4. 安卓 – 从一个扑动的应用程序拨打电话

    或者有更好的选择从我的应用程序拨打电话?

  5. android – 如何在Flutter中添加Webview?

    我知道可以将WebView添加为整页,但找不到任何示例代码.我假设你可以使用PageView作为它的基础,但不知道如何调用本机androidWebView并将其添加到PageView.谁能指出我正确的方向?

  6. android – 如何将消息从Flutter传递给Native?

    如果需要与特定的API/硬件组件进行交互,您如何将Flutter的信息传递回Android/Native代码?是否有任何事件频道可以通过其他方式发送信息或类似于回调?

  7. android – 如何在Flutter App中处理onPause / onResume?

    我是否过于复杂的事情?即使我的用例似乎不需要它,我仍然想知道:如何自己处理onPause/onResume事件?

  8. android – 如何使用Flutter构建Augment Reality应用程序?

    我对Android开发有一些基础知识.最近听说过Flutter并且非常有兴趣研究它.我想知道是否有可能使用颤振构建增强现实应用程序以及要实现此目的的方法?请帮忙.解决方法截至目前,颤振不支持3D.Flutter现在专注于2D,团队长期计划为颤振提供优化的3Dapi.你读了常见问题here.

  9. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  10. 利用Python上传日志并监控告警的方法详解

    这篇文章将详细为大家介绍如何通过阿里云日志服务搭建一套通过Python上传日志、配置日志告警的监控服务,感兴趣的小伙伴可以了解一下

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部