Files
flutter_common/lib/upload_image/ossUtil.dart

278 lines
9.1 KiB
Dart
Raw Normal View History

2025-10-20 10:44:59 +08:00
import 'dart:convert';
import 'dart:io';
import 'dart:math';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'dart:ui';
import 'package:crypto/crypto.dart';
import "package:dio/dio.dart";
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_common/utils/toast_utils.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:image_gallery_saver_plus/image_gallery_saver_plus.dart';
// import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
class UploadOss {
/*
* @params file
* @params rootDir oss设置的根目录文件夹名字
* @param fileType jpg,mp4等
* @param callback cancelToken便
* @param onSendProgress
*/
static Future<String> upload(
String path, {
String rootDir = "moment",
required String fileType,
required String oSSAccessKeyId,
required String policy,
required String callback,
required String signature,
required String ossDirectory,
required String ossHost,
2025-10-29 18:13:33 +08:00
bool? isShowLoading,
2025-10-20 10:44:59 +08:00
}) async {
// 生成oss的路径和文件名我这里目前设置的是moment/20201229/test.mp4
String pathName = "$rootDir/${getDate()}/app-${getRandom(12)}.$fileType";
// 请求参数的form对象
FormData formdata = FormData.fromMap({
'OSSAccessKeyId': oSSAccessKeyId,
'policy': policy,
'callback': callback,
'signature': signature,
'key': '$ossDirectory$pathName',
//上传后的文件名
'success_action_status': '200',
'file': MultipartFile.fromFileSync(
path,
contentType: fileType == 'mp4' ? null : DioMediaType("image", "jpg"),
filename: "${getRandom(12)}.$fileType",
),
});
2025-10-29 18:13:33 +08:00
if (isShowLoading == true) {
await EasyLoading.show(
// status: 'loading...',
maskType: EasyLoadingMaskType.black,
);
}
2025-10-20 10:44:59 +08:00
Dio dio = Dio();
dio.options.responseType = ResponseType.plain;
// dio.options.method = 'put';
// dio.options.contentType = "multipart/form-data;image/jpg";
try {
// 发送请求
Response response = await dio.post(
ossHost,
data: formdata,
options: Options(
contentType: "multipart/form-data;image/jpg",
headers: {'Content-Type': 'multipart/form-data;image/jpg'},
),
);
print("response ===== $response");
EasyLoading.dismiss();
// 成功后返回文件访问路径
return "$ossHost/$ossDirectory$pathName";
} on DioError catch (e) {
EasyLoading.dismiss();
print("e.message ===== ${e.message}");
print("e.data ===== ${e.response?.data}");
// print("e.headers ===== ${e.response?.headers}");
// print("e.extra ===== ${e.response?.extra}");
return '';
}
}
/*
*
* */
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 getDate() {
DateTime now = DateTime.now();
return "${now.year}${now.month}${now.day}";
}
}
class UploadWidgetOss {
static Future<String> uploadWidgetImage(
GlobalKey globalKey, {
required String oSSAccessKeyId,
required String policy,
required String callback,
required String signature,
required String ossDirectory,
required String ossHost,
}) async {
///通过globalkey将Widget保存为ui.Image
ui.Image _image = await getImageFromWidget(globalKey);
///异步将这张图片保存在手机内部存储目录下
String? localImagePath = await saveImageByUIImage(_image, isEncode: false);
///保存完毕后关闭当前页面并将保存的图片路径返回到上一个页面
String? url = await UploadOss.upload(
localImagePath,
fileType: "png",
oSSAccessKeyId: oSSAccessKeyId,
policy: policy,
callback: callback,
signature: signature,
ossDirectory: ossDirectory,
ossHost: ossHost,
);
return url;
}
// 将一个Widget转为image.Image对象
static Future<ui.Image> getImageFromWidget(GlobalKey globalKey) async {
// globalKey为需要图像化的widget的key
RenderRepaintBoundary? boundary =
globalKey.currentContext?.findRenderObject() as RenderRepaintBoundary?;
// 转换为图像
ui.Image img = await boundary!.toImage(pixelRatio: 2);
return img;
}
///将指定的文件保存到目录空间中。
///[image] 这里是使用的ui包下的Image
///[picName] 保存到本地的文件图片文件名如test_image
///[endFormat]保存到本地的文件图片文件格式如png
///[isReplace]当本地存在同名的文件图片true就是替换
///[isEncode]对保存的文件(图片)进行编码
/// 最终保存到本地的文件 (图片)的名称为 picName.endFormat
static Future<String> saveImageByUIImage(ui.Image image,
{String? picName,
String endFormat = "png",
bool isReplace = true,
bool isEncode = true}) async {
///获取本地磁盘路径
/*
* Android平台中获取的是/data/user/0/com.studyyoun.flutterbookcode/app_flutter
* iOS平台获取的是Documents路径
*/
Directory appDocDir = await getApplicationDocumentsDirectory();
String appDocPath = appDocDir.path;
///拼接目录
if (picName == null || picName.trim().isEmpty) {
///当用户没有指定picName时取当前的时间命名
picName = "${DateTime.now().millisecond.toString()}.$endFormat";
} else {
picName = "$picName.$endFormat";
}
if (isEncode) {
///对保存的图片名字加密
picName = md5.convert(utf8.encode(picName)).toString();
}
appDocPath = "$appDocPath/$picName";
///校验图片是否存在
var file = File(appDocPath);
bool exist = await file.exists();
if (exist) {
if (isReplace) {
///如果图片存在就进行删除替换
///如果新的图片加载失败,那么旧的图片也被删除了
await file.delete();
} else {
///如果图片存在就不进行下载
return "";
}
}
ByteData? byteData = await image.toByteData(format: ImageByteFormat.png);
Uint8List pngBytes = byteData!.buffer.asUint8List();
///将Uint8List的数据格式保存
await File(appDocPath).writeAsBytes(pngBytes);
return appDocPath;
}
//申请存本地相册权限
static Future<bool> getPormiation() async {
if (Platform.isIOS) {
var status = await Permission.photos.status;
if (status.isDenied) {
Map<Permission, PermissionStatus> statuses = await [
Permission.photos,
].request();
// saveImage(globalKey);
}
return status.isGranted;
} else {
var status = await Permission.storage.status;
if (status.isDenied) {
Map<Permission, PermissionStatus> statuses = await [
Permission.storage,
].request();
}
return status.isGranted;
}
}
///保存到相册
static void savePhoto(GlobalKey globalKey) async {
RenderRepaintBoundary? boundary =
globalKey.currentContext!.findRenderObject() as RenderRepaintBoundary?;
double dpr = ui.window.devicePixelRatio; // 获取当前设备的像素比
var image = await boundary!.toImage(pixelRatio: dpr);
// 将image转化成byte
ByteData? byteData = await image.toByteData(format: ImageByteFormat.png);
//获取保存相册权限,如果没有,则申请改权限
bool permition = await getPormiation();
var status = await Permission.photos.status;
if (permition) {
if (Platform.isIOS) {
if (status.isGranted) {
Uint8List images = byteData!.buffer.asUint8List();
final result = await ImageGallerySaverPlus.saveImage(images,
quality: 60, name: "hello");
// EasyLoading.showToast("保存成功");
ToastUtils.showToast(msg: "保存成功");
}
if (status.isDenied) {
print("IOS拒绝");
}
} else {
//安卓
if (status.isGranted) {
print("Android已授权");
Uint8List images = byteData!.buffer.asUint8List();
final result =
await ImageGallerySaverPlus.saveImage(images, quality: 60);
if (result != null) {
// EasyLoading.showToast("保存成功");
ToastUtils.showToast(msg: "保存成功");
} else {
print('error');
// toast("保存失败");
}
}
}
} else {
//重新请求--第一次请求权限时,保存方法不会走,需要重新调一次
savePhoto(globalKey);
}
}
}