一.首先获取文件的本地路径。
二.调后台接口返回oss图片上传需要的参数:accessKeyId, accessKeySecret, bucket, endPoint ,securityToken。
三.对数据进行处理,设置请求的参数
四.获取dio请求返回的路径
使用的依赖:
dio: ^5.0.0
crypto: ^3.0.2 #加密处理
intl: ^0.18.0 #国际化 因为请求参数需要设置日期
oss图片上传dart文件如下所示:
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';
import '../constants/constants.dart';
import 'package:intl/date_symbol_data_local.dart';//intl包下的
String ossAccessKeyId = '替换成自己的accessKeyId';
String ossAccessKeySecret = '替换成自己的accessKeySecret';
// oss设置的bucket的名字
String bucketName = '替换成自己的bucket';
String ossEndPoint = '替换成自己的endPoint';//oss-cn-shanghai.aliyuncs.com
String ossSecurityToken = '替换成自己的securityToken';
String host = "$bucketName.$ossEndPoint";
String url = 'https://$host';
class OssUtil{
OssUtil._internal();
factory OssUtil() => _instance;
static late final OssUtil _instance = OssUtil._internal();
Future<String> ossUploadImage(Uint8List imageData,String pathName,
{required String fileType, String? directory = "community"}) async {
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 = "/$bucketName/$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;//必须要设置日期 不设置日期报错 403
handler.next(options);
}));
try {
// 发送请求
var resultUrl = url + "/$pathName";
//必须转成这个类型才可以
Stream<List<int>> stream = Stream.value(imageData);
var rep = await dio.put(resultUrl, data: stream);
// 成功后返回文件访问路径
return UPLOAD_IMAGE_BASE_URL+"$pathName";
} catch (e) {
return '';
}
}
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;
}
//这个时间必须调用初始化,并且的时间要减去8小时,要不然会报错,服务器时间和请求时间相差太大,因为是GMT时间,所以当前时间我们是东八区的时间,所以相差8小时。
String getGMTDateString() {
initializeDateFormatting();
var date = DateTime.now();
date = date.subtract(const Duration(hours: 8));//当前时间减去8个小时
// date = date.add(const Duration(hours: 8));//当前时间加上8个小时
return DateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", 'en').format(date);
}
}
此类使用方式:
stsUploadResponse(File file) async{
try {
if (!LoginPrefs(context).isLogin()) {
LoginPrefs(context).logout();
Navigator.of(context)
.pushNamedAndRemoveUntil("login", ModalRoute.withName("login"));
return;
}
StsUploadResponseRequestEntity stsUploadResponseRequestEntity=new StsUploadResponseRequestEntity();
stsUploadResponseRequestEntity.fileType=1;
stsUploadResponseRequestEntity.fileName=file.path;
StsUploadResponseResponseEntity stsUploadResponseResponseEntity =
await NetWorkWithToken(context).stsUploadResponse(stsUploadResponseRequestEntity);//调接口获取oss需要的参数
if (stsUploadResponseResponseEntity != null) {
String accessKeyId=stsUploadResponseResponseEntity.accessKeyId;
String accessKeySecret=stsUploadResponseResponseEntity.accessKeySecret;
String securityToken=stsUploadResponseResponseEntity.securityToken;
String bucket=stsUploadResponseResponseEntity.bucket;
String endPoint=stsUploadResponseResponseEntity.endPoint;
String ossFileFullName=stsUploadResponseResponseEntity.ossFileFullName;
ossAccessKeyId=accessKeyId;
ossAccessKeySecret=accessKeySecret;
bucketName=bucket;
ossEndPoint=endPoint;
ossSecurityToken=securityToken;
String fileType=ossFileFullName.substring(ossFileFullName.lastIndexOf('.')+1);
print(fileType);
Uint8List imageData;
imageData=await file.readAsBytes();
String path=await OssUtil().ossUploadImage(imageData, ossFileFullName,fileType: fileType);
print('阿里云返回的路径:'+path);
return path;
}
} on DioError catch (e) {
print(e.message!);
} finally {}
}