需求
上傳視頻到oss梅誓,之前是走后端上傳到oss沽讹,會(huì)有一個(gè)問題就是我要先上傳給后端,后端再上傳給oss就會(huì)導(dǎo)致上傳多次藻烤,消耗時(shí)間過長(zhǎng)影響用戶體驗(yàn)绷雏,所以我參考文檔寫了直接上傳到阿里云oss獲取到文件訪問路徑。
代碼實(shí)現(xiàn)
以下是我寫的一個(gè)上傳oss的類怖亭,只需要替換ossAccessKeyId涎显, ossAccessKeySecret, bucket依许, url棺禾, expiration這幾個(gè)參數(shù)就可以直接實(shí)現(xiàn)上傳
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設(shè)置的bucket的名字
static String bucket = 'bucketName';
// 發(fā)送請(qǐng)求的url,根據(jù)你自己設(shè)置的是哪個(gè)城市的
static String url = 'https://$bucket.oss-cn-hangzhou.aliyuncs.com';
// 過期時(shí)間
static String expiration = '2025-01-01T12:00:00.000Z';
/**
* @params file 要上傳的文件對(duì)象
* @params rootDir 阿里云oss設(shè)置的根目錄文件夾名字
* @param fileType 文件類型例如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, 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;
//創(chuàng)建dio對(duì)象
Dio dio = new Dio(options);
// 生成oss的路徑和文件名我這里目前設(shè)置的是moment/20201229/test.mp4
String pathName = '$rootDir/${getDate()}/${getRandom(12)}.${fileType == null ? getFileType(file.path) : fileType}';
// 請(qǐng)求參數(shù)的form對(duì)象
FormData data = new FormData.fromMap({
'key': pathName,
'policy': getSplicyBase64(policyText),
'OSSAccessKeyId': ossAccessKeyId,
'success_action_status': '200', //讓服務(wù)端返回200峭跳,不然膘婶,默認(rèn)會(huì)返回204
'signature': signature,
'contentType': 'multipart/form-data',
'file': MultipartFile.fromFileSync(file.path),
});
Response response;
CancelToken uploadCancelToken = CancelToken();
callback ?? callback(uploadCancelToken);
try {
// 發(fā)送請(qǐng)求
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);
}
}
/*
* 生成固定長(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ù)圖片本地路徑獲取圖片名稱
* */
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) {
//進(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);
//通過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;
}
}
調(diào)用上傳的例子
其他參事自己根據(jù)自己情況上傳
Future<String> uploadFile(File file, { Function onSendProgress, Function callback}) async {
final String url = await UploadOss.upload(file: file, onSendProgress: onSendProgress, callback: callback);
return url;
}
參考文檔
部分內(nèi)容參考https://blog.csdn.net/yj909364/article/details/105415305