flutter項(xiàng)目使用阿里云oss上傳展哭,直接貼代碼
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'dart:math';
import "dart:io";
import "package:dio/dio.dart";
const String ossAccessKeyId = 'ossAccessKeyId';
const String ossAccessKeySecret = 'ossAccessKeySecret';
// oss設(shè)置的bucket的名字
const String bucket = 'bucketName';
// 發(fā)送請(qǐng)求的url,
const String url = 'https://$bucket.oss-cn-hangzhou.aliyuncs.com';
// 過(guò)期時(shí)間
const String expiration = '2075-01-01T12:00:00.000Z';
class OssUtil {
//驗(yàn)證文本域
static String _policyText =
'{"expiration": "$expiration","conditions": [["content-length-range", 0, 1048576000]]}'; //UTC時(shí)間+8=北京時(shí)間
//進(jìn)行utf8編碼
// ignore: non_constant_identifier_names
static List<int> _policyText_utf8 = utf8.encode(_policyText);
//進(jìn)行base64編碼
static String policy = base64.encode(_policyText_utf8);
//再次進(jìn)行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簽名參數(shù)
*/
String getSignature(String _accessKeySecret) {
//進(jìn)行utf8 編碼
// ignore: non_constant_identifier_names
List<int> AccessKeySecretUtf8 = utf8.encode(_accessKeySecret);
//通過(guò)hmac,使用sha1進(jìn)行加密
List<int> signaturePre =
new Hmac(sha1, AccessKeySecretUtf8).convert(_policy_utf8).bytes;
//最后一步湃窍,將上述所得進(jìn)行base64 編碼
String signature = base64.encode(signaturePre);
return signature;
}
// ignore: slash_for_doc_comments
/**
* 生成上傳上傳圖片的名稱(chēng) ,獲得的格式:photo/20171027175940_oCiobK
* 可以定義上傳的路徑uploadPath(Oss中保存文件夾的名稱(chēng))
* @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;
}
var imageType =
filePath?.substring(filePath.lastIndexOf("."), filePath.length);
return '$imageMame$imageType';
}
String getImageName(String filePath) {
String imageMame = "";
var timestamp = new DateTime.now().millisecondsSinceEpoch;
imageMame = 'app' + timestamp.toString() + "_" + getRandom(6);
var imageType =
filePath?.substring(filePath.lastIndexOf("."), filePath.length);
return '$imageMame$imageType';
}
/*
* 生成固定長(zhǎng)度的隨機(jī)字符串
* */
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;
}
/*
* 根據(jù)圖片本地路徑獲取圖片名稱(chēng)
* */
String getImageNameByPath(String filePath) {
// ignore: null_aware_before_operator
return filePath?.substring(filePath.lastIndexOf("/") + 1, filePath.length);
}
}
class UploadOss {
// 過(guò)期時(shí)間
static String expiration = "2050-01-01T12:00:00.000Z";
/*
* @params file 要上傳的文件對(duì)象
* @params rootDir 阿里云oss設(shè)置的根目錄文件夾名字
* @param fileType 文件類(lèi)型例如jpg,mp4等
* @param callback 回調(diào)函數(shù)我這里用于傳cancelToken,方便后期關(guān)閉請(qǐng)求
* @param onSendProgress 上傳的進(jìn)度事件
*/
static Future<String> upload(File file,
{String rootDir = "moment", String fileType}) async {
// 生成oss的路徑和文件名我這里目前設(shè)置的是moment/20201229/test.mp4
String pathName =
"$rootDir/${getDate()}/app-${getRandom(12)}.${fileType == null ? getFileType(file.path) : fileType}";
// 請(qǐng)求參數(shù)的form對(duì)象
FormData formdata = new FormData.fromMap({
//文件名匪傍,隨意
'Filename': OssUtil.instance.getImageName(file.path),
//"可以填寫(xiě)文件夾名(對(duì)應(yīng)于oss服務(wù)中的文件夾)/" + fileName
'key': pathName, //上傳后的文件名
'policy': OssUtil.policy,
//Bucket 擁有者的AccessKeyId您市。
'OSSAccessKeyId': ossAccessKeyId,
//讓服務(wù)端返回200,不然析恢,默認(rèn)會(huì)返回204
'success_action_status': '200',
'signature': OssUtil.instance.getSignature(ossAccessKeySecret),
'file': MultipartFile.fromFileSync(file.path)
//必須放在參數(shù)最后
});
Dio dio = Dio();
dio.options.responseType = ResponseType.plain;
try {
// 發(fā)送請(qǐng)求
await dio.post(url, data: formdata);
// 成功后返回文件訪問(wèn)路徑
return "${url}/$pathName";
} catch (e) {
return '';
}
}
/*
* 生成固定長(zhǎng)度的隨機(jī)字符串
* */
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;
}
/*
* 根據(jù)圖片本地路徑獲取圖片名稱(chēng)
* */
static String getImageNameByPath(String filePath) {
// ignore: null_aware_before_operator
return filePath?.substring(filePath.lastIndexOf("/") + 1, filePath.length);
}
/**
* 獲取文件類(lèi)型
*/
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) {
//進(jìn)行utf8編碼
List<int> policyText_utf8 = utf8.encode(policyText);
//進(jìn)行base64編碼
String policy_base64 = base64.encode(policyText_utf8);
return policy_base64;
}
/// 獲取簽名
static String getSignature(String policyText) {
//進(jìn)行utf8編碼
List<int> policyText_utf8 = utf8.encode(policyText);
//進(jìn)行base64編碼
String policy_base64 = base64.encode(policyText_utf8);
//再次進(jìn)行utf8編碼
List<int> policy = utf8.encode(policy_base64);
//進(jìn)行utf8 編碼
List<int> key = utf8.encode(ossAccessKeySecret);
//通過(guò)hmac,使用sha1進(jìn)行加密
List<int> signature_pre = Hmac(sha1, key).convert(policy).bytes;
//最后一步墨坚,將上述所得進(jìn)行base64 編碼
String signature = base64.encode(signature_pre);
return signature;
}
}
(參考了一些文章,不記得鏈接了映挂,如果原博主看到泽篮,請(qǐng)留言,把原鏈接附上柑船,見(jiàn)諒帽撑,謝謝)