【flutter直接上传图片到阿里云OSS】

flutter直接上传文件到阿里云需要获取凭证,通过调用阿里云获取凭证的接口能拿到下面这些参数

{
        "StatusCode": 200,
          "AccessKeyId": "STS.NSsrKZes4cqm.....",
          "AccessKeySecret": "7eGnLZaEFsRCGYJAnrtdE9n.....",
          "Expiration": "2020-04-08T03:44:21Z",
          "SecurityToken": "CAISlQJ1q6Ft5B2y....."
  }

获取凭证的接口一般是后台去对接阿里云,前端调后台接口即可。(STS.的这种AccessKeyId安全性高一些)
1.获取OSSToken信息

import 'dart:math';
import 'package:jade/https/HttpApplication.dart';
import 'package:jade/utils/alioss/AliOSSAccessTokenInfoBean.dart';
import 'package:intl/intl.dart';
import 'dart:typed_data';
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'package:uuid/uuid.dart';


class OSSHelper{

  //从给定的字母中生成随机字符串
  String getRandom(int num) {
    String alphabet = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
    String left = "";
    for (var i = 0; i < num; i++) {
      left = left + alphabet[Random().nextInt(alphabet.length)];
    }
    return left;
  }

  //这个时间要注意
  String getGMTDateString() {
    var date = DateTime.now();
    date = date.subtract(const Duration(hours: 8));
    return DateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", 'en').format(date);
  }


  ///使用md5加密
  String generateMD5(String data) {
    Uint8List content = new Utf8Encoder().convert(data);
    Digest digest = md5.convert(content);
    return digest.toString();
  }
  
  
  httpGetStsInfo({Function callback}){
  //根据后台给定的规则配置uuid
    var uuid = Uuid();
    String uuidStr = uuid.v4().replaceAll('-', ''); //去掉uuid中的‘-’,获取到32位


    String nowDate = DateTime.now().toString().substring(0,19);

	//当前时间拼接uuid,并加盐(后面这串盐由后台给定)
    String md5Str = nowDate + uuidStr + 'ikloniyq8923yvakn67q4in'; 

	//调用获取OSSToken信息的接口
    HttpApplication.getInstance().alOSSStsInfo(uuidStr, nowDate, generateMD5(md5Str),
        callBack: (result){
          if(result != null){
            AliOssAccessTokenInfoBean _aliOSSAccessTokenInfoBean = AliOssAccessTokenInfoBean.fromJson(result);
            if(_aliOSSAccessTokenInfoBean != null){
              callback(_aliOSSAccessTokenInfoBean);
            }
          }
        },
        errorCallBack: (error){});
  }
}

token信息实体类

class AliOssAccessTokenInfoBean {
  AliOssAccessTokenInfoBean({
      this.securityToken, 
      this.accessKeySecret, 
      this.accessKeyId, 
      this.expiration, 
      this.statusCode,});

  AliOssAccessTokenInfoBean.fromJson(dynamic json) {
    securityToken = json['SecurityToken'];
    accessKeySecret = json['AccessKeySecret'];
    accessKeyId = json['AccessKeyId'];
    expiration = json['Expiration'];
    statusCode = json['StatusCode'];
  }
  String securityToken;
  String accessKeySecret;
  String accessKeyId;
  String expiration;
  int statusCode;

  Map<String, dynamic> toJson() {
    final map = <String, dynamic>{};
    map['SecurityToken'] = securityToken;
    map['AccessKeySecret'] = accessKeySecret;
    map['AccessKeyId'] = accessKeyId;
    map['Expiration'] = expiration;
    map['StatusCode'] = statusCode;
    return map;
  }

}

上传方法

import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';

class UploadOss {

  //请求下来的AccessKeyId
  static String ossAccessKeyId;
 //请求下来的AccessKeySecret
  static String ossAccessKeySecret;
  // oss设置的bucket列表中用来存放图片视频的文件夹的名字
  static String bucket = 'zmkx';
  // 发送请求用的url,根据你自己设置的是哪个城市的
  static String url = 'https://$bucket.oss-cn-hangzhou.aliyuncs.com';

  static String host = "$bucket.oss-cn-hangzhou.aliyuncs.com"; //写入你对应的地址

//请求下来的AccessKeySecret
  static String ossSecurityToken;

  // 过期时间  请求下来的expiration 
  static String expiration;

  /*
  * @params file 要上传的文件对象
  * @params rootDir 阿里云oss设置的根目录文件夹名字
  * @param fileType 文件类型例如jpg,mp4等
  * @param callback 回调函数我这里用于传cancelToken,方便后期关闭请求
  * @param onSendProgress 上传的进度事件
  * */

  static Future<String> upload({ Uint8List file , String rootDir = 'oss/folder', String fileName,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);

    /*dio.options.responseType = ResponseType.plain;
    dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {
      options.headers["Authorization"] = "OSS " + ossAccessKeyId + ":" + signature;
      options.headers["Host"] = host;
      options.headers["x-oss-security-token"] = ossSecurityToken;
      options.contentType = 'multipart/form-data';
      //options.headers["date"] = date;
      handler.next(options);
    }));*/

    // 生成oss的路径和文件名
    String pathName = '$rootDir/test_hyf.$fileName';

    // 请求参数的form对象
    FormData data = new FormData.fromMap({
     // 'Filename': fileName,
      'key': pathName,
      'policy': getSplicyBase64(policyText),
      'OSSAccessKeyId': ossAccessKeyId,
      'success_action_status': '200', //OSSToken信息里的StatusCode是200我设置成200,阿里云默认返回204
      'signature': signature,
      'x-oss-security-token': ossSecurityToken,
      'contentType': 'multipart/form-data',
      'file': MultipartFile.fromBytes(file),
    });

    Response response;

    print('url = $url');

    try {
      // 发送请求
      response = await dio.post(url, data: data);
      // 成功后返回文件访问路径
      if(response.statusCode == 200){ //获取OSSToken信息接口的StatusCode返多少就判断等于多少
        return '$url/$pathName';
      }
    } catch(e) {
      throw(e.message);
    }
  }


/*
  *
  * File 类型文件上传 (多图上传)
  * @params file 要上传的文件对象
  * @params rootDir 阿里云oss设置的根目录文件夹名字(存放文件的那个文件夹)
  * @param fileType 文件类型例如jpg,mp4等
  * @param callback 回调函数我这里用于传cancelToken,方便后期关闭请求
  * @param onSendProgress 上传的进度事件
  * */

  static Future<List<String>> uploadByFileList({ List<File> fileList, String rootDir = 'oss/folder', String fileName,Function callback, Function onSendProgress, Function onOnlyOneFileSendProgress}) 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返回的图片链接
    List<String> imageUrlList = [];

    int uploadIndex;
    int originalWidth,originalHeight;

    // 生成oss的路径和文件名我这里目前设置的是moment/20201229/test.mp4
    // String pathName = '$rootDir/${getDate()}/${getRandom(12)}.${fileType == null ? getFileType(file.path) : fileType}';

    for (int i = 0; i < fileList.length; i++) {
      final time = DateTime.now();
      String a = '$time';
      a= a.substring(0,10);
      String pathName = '$rootDir/test_hyf$a${getRandom(12)}.${getFileType(fileList[i].path)}';
	
	  //获取本地图片的宽高		
      originalWidth =  await Utils().getLocalImageWidth(fileList[i]);
      originalHeight = await Utils().getLocalImageHeight(fileList[i]);

      // 请求参数的form对象
      FormData data = new FormData.fromMap({
        // 'Filename': fileName,
        'key': pathName,
        'policy': getSplicyBase64(policyText),
        'OSSAccessKeyId': ossAccessKeyId,
        'success_action_status': '200', //让服务端返回200,不然,默认会返回204
        'signature': signature,
        'x-oss-security-token': ossSecurityToken,
        'contentType': 'multipart/form-data',
        'file': MultipartFile.fromFileSync(fileList[i].path,/*filename: '$'*/),
      });

      Response response;

      print('阿里云url = $url');

      try {
        // 发送请求
        response = await dio.post(url, data: data,
        onSendProgress: (count, data){
              if(fileList.length == 1){
                //如果上传图片总数只有一张,则将这张图片的上传进度回调出去
                var _progress = count / data;
                onOnlyOneFileSendProgress(_progress);
              }
            });
        // 成功后返回文件访问路径
        if(response.statusCode == 200){ //获取OSSToken信息接口的StatusCode返多少就判断等于多少
          print('阿里OSS返回的文件地址[$i] = $url/$pathName');
          uploadIndex = i + 1;
          imageUrlList.add('$url/$pathName + '?Size=${originalWidth}x${originalHeight}');
        }
      } catch(e) {
        throw(e.message);
      }
    }
    // 图片上传结束
    if (fileList.length > uploadIndex) {
      // 部分图片上传失败
      uploadIndex = null;
      print('部分图片上传失败,从第${uploadIndex + 1}张失败');
      //如果有部分图片上传失败则清空已经上传返还的图片链接(图片上传失败)
      imageUrlList.clear();
    }
    return Future.value(imageUrlList);
  }


  /*
  *
  * 通过文件路径上传文件 (多图上传)
  * @params file 要上传的文件对象
  * @params rootDir 阿里云oss设置的根目录文件夹名字(存放文件的那个文件夹)
  * @param fileType 文件类型例如jpg,mp4等
  * @param callback 回调函数我这里用于传cancelToken,方便后期关闭请求
  * @param onSendProgress 上传的进度事件
  * */

  static Future<List<String>> uploadByPathList({ List<String> fileList, String rootDir = 'oss/folder', String fileName,Function callback, Function onSendProgress,Function onOnlyOneFileSendProgress}) 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返回的图片链接
    List<String> imageUrlList = [];

    int uploadIndex;
    int originalWidth,originalHeight;

    // 生成oss的路径和文件名我这里目前设置的是moment/20201229/test.mp4

    for (int i = 0; i < fileList.length; i++) {
      final time = DateTime.now();
      String a = '$time';
      a= a.substring(0,10);
      String _fileType = getFileType(fileList[i].substring(fileList[i].lastIndexOf("/") + 1, fileList[i].length));
      String pathName = '$rootDir/test_hyf$a${getRandom(12)}.$_fileType';

	  //获取本地图片的宽高		
      originalWidth =  await Utils().getLocalImageWidth(fileList[i]);
      originalHeight = await Utils().getLocalImageHeight(fileList[i]);

      // 请求参数的form对象
      FormData data = new FormData.fromMap({
        'key': pathName,
        'policy': getSplicyBase64(policyText),
        'OSSAccessKeyId': ossAccessKeyId,
        'success_action_status': '200', //让服务端返回200,不然,默认会返回204
        'signature': signature,
        'x-oss-security-token': ossSecurityToken,
        'contentType': 'multipart/form-data',
        'file': MultipartFile.fromFileSync(fileList[i],/*filename: '$'*/),
      });

      Response response;

      print('阿里云url = $url');

      try {
        // 发送请求
        response = await dio.post(url, data: data,
        onSendProgress: (count, data){
              if(fileList.length == 1){
                //如果上传图片总数只有一张,则将这张图片的上传进度回调出去
                var _progress = count / data;
                onOnlyOneFileSendProgress(_progress);
              }
            });
        // 成功后返回文件访问路径
        if(response.statusCode == 200){ //获取OSSToken信息接口的StatusCode返多少就判断等于多少
          print('阿里OSS返回的文件地址[$i] = $url/$pathName');
          uploadIndex = i + 1;
          imageUrlList.add('$url/$pathName' + '?Size=${originalWidth}x${originalHeight}');
        //  imageUrlList.add('${response.data['data'] + '?Size=${originalWidth}x${originalHeight}'}');
        }
      } catch(e) {
        throw(e.message);
      }
    }
    // 图片上传结束
    if (fileList.length > uploadIndex) {
      // 部分图片上传失败
      uploadIndex = null;
      print('部分图片上传失败,从第${uploadIndex + 1}张失败');
      //如果有部分图片上传失败则清空已经上传返还的图片链接(图片上传失败)
      imageUrlList.clear();
    }
    return Future.value(imageUrlList);
  }

 /*
  * 视频上传
  * 通过文件路径上传文件
  * @params file 要上传的文件对象
  * @params rootDir 阿里云oss设置的根目录文件夹名字(存放文件的那个文件夹)
  * @param fileType 文件类型例如jpg,mp4等
  * @param callback 回调函数我这里用于传cancelToken,方便后期关闭请求
  * @param onSendProgress 上传的进度事件
  * */

  static Future<List<String>> uploadVideoByPath({ List<String> fileList, String rootDir = 'oss/folder', String fileName,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返回的图片链接
    List<String> imageUrlList = [];

    // 生成oss的路径和文件名我这里目前设置的是moment/20201229/test.mp4

    for (int i = 0; i < fileList.length; i++) {
      final time = DateTime.now();
      String a = '$time';
      a= a.substring(0,10);
      String _fileType = getFileType(fileList[i].substring(fileList[i].lastIndexOf("/") + 1, fileList[i].length));
      String pathName = '$rootDir/test_hyf$a${getRandom(12)}.$_fileType';

      // 请求参数的form对象
      FormData data = new FormData.fromMap({
        'key': pathName,
        'policy': getSplicyBase64(policyText),
        'OSSAccessKeyId': ossAccessKeyId,
        'success_action_status': '200', //让服务端返回200,不然,默认会返回204
        'signature': signature,
        'x-oss-security-token': ossSecurityToken,
        'contentType': 'multipart/form-data',
        'file': MultipartFile.fromFileSync(fileList[i]),
      });

      Response response;
      try {
        // 发送请求
        response = await dio.post(url, data: data);
        // 成功后返回文件访问路径
        if(response.statusCode == 200){ //获取OSSToken信息接口的StatusCode返多少就判断等于多少
          print('阿里OSS返回的文件地址[$i] = $url/$pathName');

          imageUrlList.add('$url/$pathName');
        }
      } catch(e) {
        throw(e.message);
      }
    }
    return Future.value(imageUrlList);
  }

  /*
  * 生成固定长度的随机字符串
  * */
  static String getRandot 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;
  }
}

调用方式

import 'dart:typed_data';
import 'package:jade/utils/alioss/AliOSSAccessTokenInfoBean.dart';
import 'package:jade/utils/alioss/OSSHelper.dart';
import 'package:jade/utils/alioss/UploadOss.dart';
import 'package:flutter/material.dart';
import 'package:multi_image_picker/multi_image_picker.dart';

class AliUpLoadTest extends StatefulWidget{
  
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return _AliUpLoadTest();
  }
}

class _AliUpLoadTest extends State<AliUpLoadTest>{
  
  Widget build(BuildContext context) {
    // TODO: implement build
    return GestureDetector(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Container(
            width: 100,
            height: 60,
            color: Colors.red,
          )
        ],
      ),
      onTap: (){
      //最好是在调完接口后对对应参数进行赋值接着使用上传方法(本人写死请求下来的token信息进行测试一直报403,应该是token信息的持有时间很短)
        OSSHelper().httpGetStsInfo(callback: (aliOSSAccessTokenInfoBean){
          AliOssAccessTokenInfoBean _aliOSSAccessTokenInfoBean = aliOSSAccessTokenInfoBean;
          setState(() {
            UploadOss.ossAccessKeyId = _aliOSSAccessTokenInfoBean.accessKeyId;
            UploadOss.ossAccessKeySecret = _aliOSSAccessTokenInfoBean.accessKeySecret;
            UploadOss.expiration = _aliOSSAccessTokenInfoBean.expiration;
            UploadOss.ossSecurityToken = _aliOSSAccessTokenInfoBean.securityToken;
          });
          openPhotoSelect(1);

        });
      },
    );
  }


  openPhotoSelect(int maxImages) async {
    try {
      List<Asset> images = await MultiImagePicker.pickImages(
        maxImages: 1,
        enableCamera: true,
        cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
        materialOptions: MaterialOptions(
          actionBarTitle: "图片选择",
          allViewTitle: "所有图片",
          useDetailsView: true,
          selectCircleStrokeColor: "#4dc8b6",
          selectionLimitReachedText: "最多选择$maxImages张图片",
        ),
      );
      Asset asset = images[0];
      uploadFile(asset);
    } on Exception catch (e) {
      print(e);
    }
  }

  Future<String> uploadFile(Asset asset ) async {
    ByteData byteData = await asset.getByteData();
    List<int> imageData = byteData.buffer.asUint8List();
    final String url = await UploadOss.upload(file: imageData,fileName:asset.name);
    print('OSS返回的文件地址 = $url');
    return url;
  }
}

以上直接是上传图片到阿里云成功调通了的demo,并没由做多图的封装。UploadOss是在网上找的工具类,百分之九十九搜出来都是这个。
还有找到另外一个工具类,不过并没有用测试过,代码:

import 'dart:collection';
import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';

import 'package:crypto/crypto.dart';
import 'package:dio/dio.dart';
import 'package:intl/intl.dart';

class UploadUtil {

  String host = "$bucket.oss-cn-hangzhou.aliyuncs.com"; //写入你对应的地址

  // 发送请求的url,根据你自己设置的是哪个城市的
  static String url = 'https://$bucket.oss-cn-hangzhou.aliyuncs.com';

  static String ossAccessKeyId = 'STS.NV864oDQJQELywUH427zm7V46';

  static String ossAccessKeySecret = '2KAmY77P6z9C3cEMFrdESxSXdzUSpZucW6PEo3uxpewy';

  static String ossSecurityToken = 'CAISoQJ1q6Ft5B2yfSjIr5WNfY7bqY5r5oene1HkrDRnO/VB2JOf1Dz2IH1JfnVtCO4et/w3mWhS5/cZlrhIWoR4XkHeStBr1ZlM6gKmZdIFGEcHJOVW5qe+EE2/VjThvqaLEeCbIfrZfvCyER+m8gZ43br9cxi7QlWhKufnoJV7b9MRLG7aCD1dH4VuOxdFos0XPmerZpTLCBPxhXfKB0dFoxd1jXgFiZ6y2cqB8BHT/iqYv+YevNb2OYP2LZsuboV6UMfy2/dtMaTG1CJd8V8I1t8v0vEfqG2W74/AWQQMvEzeCYeOrI0zdj0eT7MhBqtJoML7kfBFoeHJn+z1sU0QYLsJDnWBHNn4mJacQrL4bcxYb7/+PG/WycGUJm9lZMuVjuJxGoABb28iVg9ghcjTcfGgi3kkzknftUIsfBQieSUlngPouzWRJQYpvb74JlVLxbVtnxrW8J/LBqlSVjRlW++1WPxgq+wX4K5KwJ8zwFwM61JnNJsm4eCMsG2lgzZw2qAIWh2cfw1wrGdz20sWBaDxy9ne/AtHiEEc2H6E23TQIcfoNtU=';

  // oss设置的bucket的名字
  static String bucket = 'zmkx';

  // 过期时间
  static String expiration = '2023-08-22T03:45:25Z';


  Future<String> ossUploadImage(Uint8List imageData,
      { String fileType, String directory = "community"}) async {
    //命名
    String timeStr = DateFormat("yyyyMMdd", 'en').format(DateTime.now());
    String pathName = "img/$directory/app$timeStr${getRandom(12)}.$fileType";

    String date = getGMTDateString();

    String contentType = 'image/$fileType';
    //签名相关
    //请求头
    SplayTreeMap<String, String> treeMap = SplayTreeMap();
    treeMap["Content-Type".toLowerCase()] = contentType.trim();
    treeMap["Content-MD5".toLowerCase()] = "";
    treeMap["Date".toLowerCase()] = date.trim();
    treeMap["x-oss-security-token".toLowerCase()] = ossSecurityToken.trim();
    String headString = "PUT\n";
    treeMap.forEach((key, value) {
      if (key.startsWith("x-oss-")) {
        headString += key;
        headString += ':';
        headString += value;
      } else {
        headString += value;
      }
      headString += '\n';
    });

    String contentString = "/$bucket/$pathName";
    String contentToSign = headString + contentString;

    List<int> key = utf8.encode(ossAccessKeySecret);
    List<int> data = utf8.encode(contentToSign);
    var signaturePre = Hmac(sha1, key)
        .convert(data)
        .bytes;
    //最后一步,将上述所得进行base64 编码
    String signature = base64.encode(signaturePre);
    String signatureA = "OSS " + ossAccessKeyId + ":" + signature;

    Dio dio = Dio();
    dio.options.responseType = ResponseType.plain;
    dio.interceptors.add(InterceptorsWrapper(onRequest: (options, handler) {
      options.headers["Authorization"] = signatureA;
      options.headers["Host"] = host;
      options.headers["x-oss-security-token"] = ossSecurityToken;
      options.contentType = contentType;
      options.headers["date"] = date;
      handler.next(options);
    }));
    try {
      // 发送请求
      var resultUrl = url /*+ "/$pathName"*/;
      //必须转成这个类型才可以
      Stream<List<int>> stream = Stream.value(imageData);
      var rep = await dio.put(resultUrl, data: stream);
      // 成功后返回文件访问路径
      return "$url/$pathName";
    } catch (e) {
      return '错误:${e.toString()}';
    }
  }

  String getRandom(int num) {
    String alphabet = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM";
    String left = "";
    for (var i = 0; i < num; i++) {
      left = left + alphabet[Random().nextInt(alphabet.length)];
    }
    return left;
  }

//这个时间要注意
  String getGMTDateString() {
    var date = DateTime.now();
    date = date.subtract(const Duration(hours: 8));
    return DateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", 'en').format(date);
  }

  /*获取文件类型
  * */
  static String getFileType(String path) {
    print(path);
    List<String> array = path.split('.');
    return array[array.length -1];
  }

}
C# provides two main data structures for storing collections of elements: List and Array. Both List and Array are used to store and manipulate a collection of items, but they have some differences in terms of flexibility and functionality. An Array is a fixed-size collection of elements of the same type. Once an array is created, its size cannot be changed. You need to specify the size of the array when declaring it. Array elements can be accessed using an index, starting from 0. Here's an example of creating and accessing elements in an array: ```csharp int[] numbers = new int[5]; // Creating an array of size 5 numbers[0] = 1; // Accessing and setting the value at index 0 int firstNumber = numbers[0]; // Accessing the value at index 0 ``` On the other hand, List is a dynamic collection that can grow or shrink in size. It allows adding, removing, and modifying elements easily. List provides several methods and properties to manipulate the collection efficiently. Here's an example of creating and manipulating elements in a List: ```csharp List<int> numbers = new List<int>(); // Creating an empty list numbers.Add(1); // Adding an element to the list int firstNumber = numbers[0]; // Accessing the value at index 0 numbers.Remove(1); // Removing an element from the list ``` In summary, Arrays have a fixed size, while Lists can dynamically grow or shrink. Arrays are generally more efficient in terms of memory, but Lists provide more flexibility and functionality for manipulating collections.
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值