flutter直接上傳文件到阿里云oss
代碼實現(xiàn)
以下是我寫的一個上傳oss的類,只需要替換ossAccessKeyId, ossAccessKeySecret, bucket, url, expiration這幾個參數(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ā)送請求的url,根據(jù)你自己設(shè)置的是哪個城市的
static String url = 'https://$bucket.oss-cn-hangzhou.aliyuncs.com';
// 過期時間
static String expiration = '2025-01-01T12:00:00.000Z';
/**
* @params file 要上傳的文件對象
* @params rootDir 阿里云oss設(shè)置的根目錄文件夾名字
* @param fileType 文件類型例如jpg,mp4等
* @param callback 回調(diào)函數(shù)我這里用于傳cancelToken,方便后期關(guān)閉請求
* @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對象
Dio dio = new Dio(options);
// 生成oss的路徑和文件名我這里目前設(shè)置的是moment/20201229/test.mp4
String pathName = '$rootDir/${getDate()}/${getRandom(12)}.${fileType == null ? getFileType(file.path) : fileType}';
// 請求參數(shù)的form對象
FormData data = new FormData.fromMap({
'key': pathName,
'policy': getSplicyBase64(policyText),
'OSSAccessKeyId': ossAccessKeyId,
'success_action_status': '200', //讓服務(wù)端返回200,不然,默認(rèn)會返回204
'signature': signature,
'contentType': 'multipart/form-data',
'file': MultipartFile.fromFileSync(file.path),
});
Response response;
CancelToken uploadCancelToken = CancelToken();
callback ?? callback(uploadCancelToken);
try {
// 發(fā)送請求
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);
}
}
/*
* 生成固定長度的隨機字符串
* */
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;
}
另一種方法
目前阿里沒有針對Flutter有官方SDK可集成, 但是有人對Flutter的上傳有封裝庫https://pub.dev/packages/aly_oss#-example-tab-, 所以我們只能通過post提交PostObject的形式來上傳;
準(zhǔn)備工作:
1、獲取OSS憑證地址(your oss_sts_server), 通知get直接獲取static String ossServerUrl = 'http://.../sts-server/sts.php';
2、上傳的存儲地址(桶名):static String ossEndPointCdn = '<your endpointcdn>';
// 通過ossServerUrl直接get獲取到如下數(shù)據(jù)
{
"StatusCode": 200,
"AccessKeyId": "STS.NSsrKZes4cqm.....",
"AccessKeySecret": "7eGnLZaEFsRCGYJAnrtdE9n.....",
"Expiration": "2020-04-08T03:44:21Z",
"SecurityToken": "CAISlQJ1q6Ft5B2y....."
}
//表單需要的參數(shù): AccessKeyId、AccessKeySecret、SecurityToken;
FormData formdata = new FormData.from({
//文件名,隨意
'Filename': OssUtil.instance.getImageName(filePath),
//"可以填寫文件夾名(對應(yīng)于oss服務(wù)中的文件夾)/" + fileName
'key': uploadName,//上傳后的文件名
'policy': OssUtil.policy,
//Bucket 擁有者的AccessKeyId。
'OSSAccessKeyId': data['AccessKeyId'],
//讓服務(wù)端返回200,不然,默認(rèn)會返回204
'success_action_status': '200',
'signature': OssUtil.instance.getSignature(data['AccessKeySecret']),
//臨時用戶授權(quán)時必須,需要攜帶后臺返回的security-token
'x-oss-security-token': data['SecurityToken'],
'file': new UploadFileInfo(
file, OssUtil.instance.getImageNameByPath(filePath))
//必須放在參數(shù)最后
});
//然后通過存儲地址直接把表單(formdata)上傳上去;
Dio dio=Dio();
dio.options.responseType=ResponseType.plain;
Response response=awaitdio.post(<ossEndPointCdn>,data:formData);
......
tips: 上傳成功后圖片地址 imageUrl = ossEndPointCdn + '/' + uploadName;
給一個工具類
import 'dart:convert';
import 'package:crypto/crypto.dart';
import 'dart:math';
class OssUtil {
獲取
//驗證文本域
static String _policyText =
'{"expiration": "2069-05-22T03:15:00.000Z","conditions": [["content-length-range", 0, 1048576000]]}';//UTC時間+8=北京時間
//進(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);
//通過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
/**
* 生成上傳上傳圖片的名稱 ,獲得的格式:photo/20171027175940_oCiobK
* 可以定義上傳的路徑uploadPath(Oss中保存文件夾的名稱)
* @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;
}
String imageType=filePath?.substring(filePath?.lastIndexOf("."),filePath?.length);
return imageMame+imageType;
}
String getImageName(String filePath) {
String imageMame = "";
var timestamp = new DateTime.now().millisecondsSinceEpoch;
imageMame =timestamp.toString()+"_"+getRandom(6);
String imageType=filePath?.substring(filePath?.lastIndexOf("."),filePath?.length);
return imageMame+imageType;
}
/*
* 生成固定長度的隨機字符串
* */
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ù)圖片本地路徑獲取圖片名稱
* */
String getImageNameByPath(String filePath) {
// ignore: null_aware_before_operator
return filePath?.substring(filePath?.lastIndexOf("/")+1,filePath?.length);
}
}
以上就是flutter直接上傳文件到阿里云oss的實現(xiàn)步驟的詳細(xì)內(nèi)容,更多關(guān)于flutter 上傳文件到阿里云oss的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android通過實現(xiàn)GridView的橫向滾動實現(xiàn)仿京東秒殺效果
這篇文章主要介紹了Android通過實現(xiàn)GridView的橫向滾動實現(xiàn)仿京東秒殺效果,實現(xiàn)代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-07-07
Jetpack?Compose?的新型架構(gòu)?MVI使用詳解
這篇文章主要介紹了Jetpack?Compose?的新型架構(gòu)?MVI使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
Android實現(xiàn)微信分享帶有縮略圖的網(wǎng)頁
最近做了一個web app的項目,要求分享web頁還要帶有圖片功能,怎么實現(xiàn)呢?今天小編給大家分享android實現(xiàn)微信分享帶有縮略圖的網(wǎng)頁功能,需要的朋友參考下2017-02-02
Android?自定義View?加?lifecycle?簡單使用詳解
本文介紹了自定義View的基本使用方法,包括onMeasure、onDraw、自定義樣式和lifecycle的使用,通過了解MeasureSpec的作用和lifecycle的控制,可以更好地管理View的生命周期,避免內(nèi)存泄露問題,感興趣的朋友一起看看吧2025-03-03
Android使用SQLiteDatabase增刪改查(CRUD)的操作教程
在 Android 中使用 SQLiteDatabase 進(jìn)行增刪改查操作是開發(fā)中的核心技能之一,下面我將詳細(xì)說明如何使用 SQLiteDatabase 進(jìn)行 CRUD 操作,需要的朋友可以參考下2025-04-04
Android 獲取正在運行的任務(wù)和服務(wù)的小例子
Android 獲取正在運行的任務(wù)和服務(wù)的小例子,需要的朋友可以參考一下2013-05-05
android webview獲取html代碼和根據(jù)id獲取value實例
這篇文章主要介紹了android webview獲取html代碼和根據(jù)id獲取value實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03

