【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}){//根据后台给定的规则配置uuidvar 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 {//请求下来的AccessKeyIdstatic String ossAccessKeyId;//请求下来的AccessKeySecretstatic 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"; //写入你对应的地址//请求下来的AccessKeySecretstatic 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);}}/** 生成固定长度的随机字符串* */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_operatorreturn 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的base64static 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 createStatereturn _AliUpLoadTest();}
}class _AliUpLoadTest extends State<AliUpLoadTest>{Widget build(BuildContext context) {// TODO: implement buildreturn 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];}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/54303.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解除用户账户控制提醒

解决用户账户控制提醒 1. 前言2. 解决用户账户控制提醒2.1 控制面板2.2 注册表2.3 UAC服务 结束语 1. 前言 当我们使用电脑时&#xff0c;有时进行安装应用或者打开应用时&#xff0c;总会弹出一个提示框&#xff0c;要选择点击是否允许程序运行&#xff1b; 系统经常弹出用户…

el-form表单el-form-item prop一次验证两个值

1.表单添加两个框&#xff0c;prop写上 <el-form :model"ruleForm" :rules"rules" ref"ruleForm" label-width"100px" > <el-form-item type"type" label"时间" prop"dateSectOne"><di…

【Git】测试持续集成——Git+Gitee+PyCharm

文章目录 概述一、使用Gitee1. 注册账号2. 绑定邮箱3. 新建仓库4. 查看项目地址 二、安装配置Git1. 下载安装包2. 校验是否安装成功。3. 配置Git4. Git命令5. Git实操 三、PyCharmGit1. 配置Git2. Clone项目3. 提交文件到服务器4. 从服务器拉取文件 概述 持续集成&#xff08;…

docker 启动命令

cd /ycw/docker docker build -f DockerFile -t jshepr:1.0 . #前面测试docker已经介绍过该命令下面就不再介绍了 docker images docker run -it -p 7003:9999 --name yyy -d jshepr:1.0 #上面运行报错 用这个 不报错就不用 docker rm yyy docker ps #查看项目日志 docker …

【javaweb】学习日记Day4 - Maven 依赖管理 Web入门

目录 一、Maven入门 - 管理和构建java项目的工具 1、IDEA如何构建Maven项目 2、Maven 坐标 &#xff08;1&#xff09;定义 &#xff08;2&#xff09;主要组成 3、IDEA如何导入和删除项目 二、Maven - 依赖管理 1、依赖配置 2、依赖传递 &#xff08;1&#xff09;查…

Docker容器学习:Dockerfile制作Web应用系统nginx镜像

目录 编写Dockerfile 1.文件内容需求&#xff1a; 2.编写Dockerfile&#xff1a; 3.开始构建镜像 4.现在我们运行一个容器&#xff0c;查看我们的网页是否可访问 推送镜像到私有仓库 1.把要上传的镜像打上合适的标签 2.登录harbor仓库 3.上传镜像 编写Dockerfile 1.文…

2000-2021年地级市产业升级、产业结构高级化面板数据

2000-2021年地级市产业升级、产业结构高级化面板数据 1、时间&#xff1a;2000-2021年 2、范围&#xff1a;地级市 3、指标&#xff1a;年份、地区、行政区划代码、地区、所属省份、地区生产总值、第一产业增加值、第二产业增加值、第三产业增加值、第一产业占GDP比重、第二…

常见的时序数据库

1.概念 时序数据库全称为时间序列数据库。时间序列数据库指主要用于处理带时间标签&#xff08;按照时间的顺序变化&#xff0c;即时间序列化&#xff09;的数据&#xff0c;带时间标签的数据也称为时间序列数据。 时间序列数据主要由电力行业、化工行业、气象行业、地理信息…

十四、pikachu之XSS

文章目录 1、XSS概述2、实战2.1 反射型XSS&#xff08;get&#xff09;2.2 反射型XSS&#xff08;POST型&#xff09;2.3 存储型XSS2.4 DOM型XSS2.5 DOM型XSS-X2.6 XSS之盲打2.7 XSS之过滤2.8 XSS之htmlspecialchars2.9 XSS之href输出2.10 XSS之JS输出 1、XSS概述 Cross-Site S…

分享一种针对uni-app相对通用的抓包方案

PART1&#xff0c;前言 近年来混合开发APP逐渐成为主流的开发模式&#xff0c;与传统的开发模式相比混合开发极大的提升了开发效率&#xff0c;同时跨平台的特性也降低了开发成本&#xff0c;一直以来混合开发被诟病的性能问题随着技术的发展也得到改善。技术的发展往往是一把…

前端需要理解的跨平台知识

混合开发是指使用多种开发模开发App的一种开发模式&#xff0c;涉及到两大类技术&#xff1a;原生 Native、Web H5。原生 Native 主要指 iOS&#xff08;Objective C&#xff09;、Android&#xff08;Java&#xff09;&#xff0c;原生开发效率较低&#xff0c;开发完成需要重…

2023-08-26力扣每日一题

链接&#xff1a; 228. 汇总区间 题意&#xff1a; 升序数组找连续区间 解&#xff1a; 简单遍历题 实际代码&#xff1a; #include<bits/stdc.h> using namespace std; vector<string> summaryRanges(vector<int>& nums) {if(!nums.size()) retu…

【Java集合学习1】ArrayList集合学习及集合概述分析

JavaArrayList集合学习及集合学习概述 一、Java集合概述 Java 集合&#xff0c; 也叫作容器&#xff0c;主要是由两大接口派生而来&#xff1a;一个是 Collection接口&#xff0c;主要用于存放单一元素&#xff1b;另一个是 Map 接口&#xff0c;主要用于存放键值对。对于Col…

Java之动态代理实践

功能概述 Java的动态代理&#xff0c;是代理模式的具体实现&#xff0c;即为其他对象提供一个代理以控制对某个对象的访问。Java的动态代理主要涉及两个类&#xff1a;java.lang.reflect.Proxy 和 java.lang.reflect.InvocationHandler&#xff0c;内部使用了缓存机制和反射机…

Apache Poi 实现Excel多级联动下拉框

由于最近做的功能&#xff0c;需要将接口返回的数据列表&#xff0c;输出到excel中&#xff0c;以供后续导入&#xff0c;且网上现有的封装&#xff0c;使用起来都较为麻烦&#xff0c;故参考已有做法封装了工具类。 使用apache poi实现excel联动下拉框思路 创建隐藏单元格&a…

如何评估开源项目的活跃度和可持续性?

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

元矿山下的音视频应用

// 近年来&#xff0c;矿业的技术和管理模式随着元宇宙的火爆和自动驾驶技术的发展逐渐变化、升级&#xff0c;进而衍生出元矿山的概念&#xff0c;音视频技术也在其中成为了关键一环。LiveVideoStackCon 2023 上海站邀请了来自希迪智驾的任思亮&#xff0c;为大家分享希迪智…

windows MFC消息demo

1、在BEGIN_MESSAGE_MAP添加MAP映射 BEGIN_MESSAGE_MAP(CdesktopTotalMapDlg, CDialogEx)ON_MESSAGE(WM_SYS_NORMAL_MSG, OnSysNormalMessage)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BUTTON_SELECTSOURCEDIR, &CdesktopTotalMapDlg::OnB…

基于神经网络的3D地质模型

地球科学家需要对地质环境进行最佳估计才能进行模拟或评估。 除了地质背景之外&#xff0c;建立地质模型还需要一整套数学方法&#xff0c;如贝叶斯网络、协同克里金法、支持向量机、神经网络、随机模型&#xff0c;以在钻井日志或地球物理信息确实稀缺或不确定时定义哪些可能是…

机器学习笔记之优化算法(十九)经典牛顿法的收敛性分析

机器学习笔记之优化算法——经典牛顿法的收敛性分析 引言回顾&#xff1a;算法的收敛性分析 Wolfe \text{Wolfe} Wolfe准则的收敛性分析梯度下降法在凸函数的收敛性分析梯度下降法在强凸函数的收敛性分析 经典牛顿法的收敛性分析收敛性定理介绍证明过程关于隐含条件的说明 引言…