feat(delete):删除里面文件夹
This commit is contained in:
142
lib/upload_image/down_load_image_tool.dart
Normal file
142
lib/upload_image/down_load_image_tool.dart
Normal file
@@ -0,0 +1,142 @@
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:dio/dio.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:permission_handler/permission_handler.dart';
|
||||
|
||||
class DownLoadImageTool {
|
||||
|
||||
// 请求照片库权限
|
||||
static Future<bool> requestPhotoPermission() async {
|
||||
// 检查当前权限状态
|
||||
var status = await Permission.photos.status;
|
||||
|
||||
if (status.isDenied) {
|
||||
// 请求权限
|
||||
status = await Permission.photos.request();
|
||||
|
||||
// 如果用户拒绝了权限,可以显示一个解释
|
||||
if (status.isPermanentlyDenied) {
|
||||
// 打开应用设置,让用户手动启用权限
|
||||
await openAppSettings();
|
||||
}
|
||||
|
||||
if (status.isDenied) {
|
||||
// 打开应用设置,让用户手动启用权限
|
||||
await openAppSettings();
|
||||
}
|
||||
}
|
||||
|
||||
return status.isGranted;
|
||||
}
|
||||
|
||||
// 或者请求存储权限(适用于Android)
|
||||
static Future<bool> requestStoragePermission() async {
|
||||
if (Platform.isAndroid) {
|
||||
// 对于Android 13及以上版本
|
||||
if (await DeviceInfoPlugin().androidInfo.then((info) => info.version.sdkInt) >= 33) {
|
||||
var status = await Permission.photos.request();
|
||||
if(status == PermissionStatus.denied){
|
||||
await requestPhotoPermission();
|
||||
}
|
||||
return status.isGranted;
|
||||
} else {
|
||||
// 对于Android 13以下版本
|
||||
var status = await Permission.storage.request();
|
||||
return status.isGranted;
|
||||
}
|
||||
} else {
|
||||
// iOS使用照片权限
|
||||
return await requestPhotoPermission();
|
||||
}
|
||||
}
|
||||
|
||||
///保存到相册
|
||||
static Future<dynamic> savePhoto({
|
||||
required String imageUrl,
|
||||
bool? isHideLoading,
|
||||
}) async {
|
||||
//获取保存相册权限,如果没有,则申请改权限
|
||||
bool permition = await requestStoragePermission();
|
||||
if (permition) {
|
||||
var result = imageRequest(
|
||||
imageUrl: imageUrl,
|
||||
isHideLoading: isHideLoading,
|
||||
);
|
||||
return result;
|
||||
} else {
|
||||
//重新请求--第一次请求权限时,保存方法不会走,需要重新调一次
|
||||
ToastUtils.showToast(msg: '请打开手机相册权限');
|
||||
// savePhoto(imageUrl: imageUrl);
|
||||
}
|
||||
}
|
||||
|
||||
static Future<dynamic> imageRequest({
|
||||
required String imageUrl,
|
||||
bool? isHideLoading,
|
||||
}) async {
|
||||
if (isHideLoading == true) {
|
||||
} else {
|
||||
await EasyLoading.show(
|
||||
// status: 'loading...',
|
||||
maskType: EasyLoadingMaskType.black,
|
||||
);
|
||||
}
|
||||
|
||||
var response = await Dio().get(
|
||||
imageUrl,
|
||||
options: Options(
|
||||
responseType: ResponseType.bytes,
|
||||
),
|
||||
);
|
||||
if (isHideLoading == true) {
|
||||
} else {
|
||||
EasyLoading.dismiss();
|
||||
}
|
||||
|
||||
final result = await ImageGallerySaverPlus.saveImage(
|
||||
Uint8List.fromList(response.data),
|
||||
quality: 60,
|
||||
name: "hello",
|
||||
isReturnImagePathOfIOS: true,
|
||||
);
|
||||
print('=result ============ $result');
|
||||
return result;
|
||||
}
|
||||
|
||||
///fetchImageAsUint8List
|
||||
static Future<Uint8List?> fetchImageAsUint8List(String imageUrl) async {
|
||||
await EasyLoading.show(
|
||||
// status: 'loading...',
|
||||
maskType: EasyLoadingMaskType.black,
|
||||
);
|
||||
try {
|
||||
var response = await Dio().get(
|
||||
imageUrl,
|
||||
options: Options(
|
||||
responseType: ResponseType.bytes,
|
||||
),
|
||||
);
|
||||
// final response = await http.get(Uri.parse(imageUrl));
|
||||
if (response.statusCode == 200) {
|
||||
EasyLoading.dismiss();
|
||||
return response.data;
|
||||
} else {
|
||||
// debugPrint('Failed to load image: ${response.statusCode}');
|
||||
EasyLoading.dismiss();
|
||||
return null;
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
EasyLoading.dismiss();
|
||||
// debugPrint('Error fetching image: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
93
lib/upload_image/download_local_tool.dart
Normal file
93
lib/upload_image/download_local_tool.dart
Normal file
@@ -0,0 +1,93 @@
|
||||
import 'dart:io';
|
||||
import 'package:dio/dio.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 DownloadLocalTool {
|
||||
/// 拿到存储路径
|
||||
/// 使用getTemporaryDirectory()方法可以获取应用程序的临时目录,该目录用于存储应用程序的临时数据。这个目录在应用程序退出后会被清空
|
||||
Future<String> getTemporaryDirectoryString() async {
|
||||
final directory = await getTemporaryDirectory();
|
||||
return directory.path;
|
||||
}
|
||||
|
||||
/// 使用getApplicationDocumentsDirectory()方法可以获取应用程序的文档目录,该目录用于存储应用程序的私有数据。
|
||||
Future<String> getApplicationDocumentsDirectoryString() async {
|
||||
final directory = await getApplicationDocumentsDirectory();
|
||||
return directory.path;
|
||||
}
|
||||
|
||||
/// 使用getExternalStorageDirectory()方法可以获取设备的外部存储目录,该目录用于存储应用程序的公共数据。需要注意的是,在某些设备上,外部存储目录可能是不可用的。
|
||||
Future<String> getExternalStorageDirectoryString() async {
|
||||
final directory = await getExternalStorageDirectory();
|
||||
return directory?.path ?? "";
|
||||
}
|
||||
|
||||
/// 创建对文件位置的引用
|
||||
Future<File> localFile(String fileName) async {
|
||||
final path = await getApplicationDocumentsDirectoryString();
|
||||
return File('$path/$fileName');
|
||||
}
|
||||
|
||||
///save
|
||||
Future<dynamic> saveNetworkVideoFile({
|
||||
required String fileName,
|
||||
required String fileUrl,
|
||||
}) async {
|
||||
final path = await getApplicationDocumentsDirectoryString();
|
||||
String savePath = "$path/$fileName ";
|
||||
// String fileUrl =
|
||||
// "https://s3.cn-north-1.amazonaws.com.cn/mtab.kezaihui.com/video/ForBiggerBlazes.mp4";
|
||||
//
|
||||
await Dio().download(fileUrl, savePath, onReceiveProgress: (count, total) {
|
||||
print("${(count / total * 100).toStringAsFixed(0)}%");
|
||||
});
|
||||
final result = await ImageGallerySaverPlus.saveFile(savePath);
|
||||
return result;
|
||||
// print(result);
|
||||
}
|
||||
|
||||
///save
|
||||
Future<dynamic> saveNetworkVideoFileExternalStorageDirectory({
|
||||
required String fileName,
|
||||
required String fileUrl,
|
||||
}) async {
|
||||
final path = await getApplicationDocumentsDirectoryString();
|
||||
String savePath = "$path/$fileName ";
|
||||
// String fileUrl =
|
||||
// "https://s3.cn-north-1.amazonaws.com.cn/mtab.kezaihui.com/video/ForBiggerBlazes.mp4";
|
||||
//
|
||||
await Dio().download(fileUrl, savePath, onReceiveProgress: (count, total) {
|
||||
print("${(count / total * 100).toStringAsFixed(0)}%");
|
||||
});
|
||||
final result = await ImageGallerySaverPlus.saveFile(savePath);
|
||||
return result;
|
||||
// print(result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// // 将数据写入文件
|
||||
// Future<File> writeCounter(int counter) async {
|
||||
// final file = await _localFile;
|
||||
// // Write the file
|
||||
// return file.writeAsString('$counter');
|
||||
// }
|
||||
//
|
||||
// // 从文件中读取数据
|
||||
// Future<int> readCounter() async {
|
||||
// try {
|
||||
// final file = await _localFile;
|
||||
// // Read the file
|
||||
// String contents = await file.readAsString();
|
||||
//
|
||||
// return int.parse(contents);
|
||||
// } catch (e) {
|
||||
// // If we encounter an error, return 0
|
||||
// return 0;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
102
lib/upload_image/look_images_widget.dart
Normal file
102
lib/upload_image/look_images_widget.dart
Normal file
@@ -0,0 +1,102 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:photo_view/photo_view.dart';
|
||||
import 'package:photo_view/photo_view_gallery.dart';
|
||||
|
||||
class LookImagesTool {
|
||||
static lookImages({
|
||||
required List<String> listData,
|
||||
int? currentPage,
|
||||
}) async {
|
||||
showDialog(
|
||||
context: Get.context!,
|
||||
builder: (_) {
|
||||
return LookImagesWidget(
|
||||
listData: listData,
|
||||
currentPage: currentPage,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class LookImagesWidget extends StatefulWidget {
|
||||
final List<String> listData;
|
||||
final int? currentPage;
|
||||
|
||||
const LookImagesWidget({
|
||||
super.key,
|
||||
required this.listData,
|
||||
this.currentPage,
|
||||
});
|
||||
|
||||
@override
|
||||
State<LookImagesWidget> createState() => _LookImagesWidgetState();
|
||||
}
|
||||
|
||||
class _LookImagesWidgetState extends State<LookImagesWidget> {
|
||||
List listData = [];
|
||||
late int currentPage;
|
||||
late int initialPage = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
listData = widget.listData;
|
||||
if (widget.currentPage == null) {
|
||||
initialPage = 0;
|
||||
currentPage = 0;
|
||||
} else {
|
||||
// initialPage = 0;
|
||||
currentPage = widget.currentPage ?? 0;
|
||||
}
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () => Get.back(),
|
||||
child: Stack(
|
||||
children: [
|
||||
Scaffold(
|
||||
backgroundColor: Colors.black,
|
||||
body: Center(
|
||||
child: PhotoViewGallery.builder(
|
||||
itemCount: listData.length,
|
||||
pageController: PageController(initialPage: currentPage),
|
||||
onPageChanged: (index) {
|
||||
setState(() {
|
||||
currentPage = index;
|
||||
});
|
||||
},
|
||||
builder: (_, index) {
|
||||
return PhotoViewGalleryPageOptions(
|
||||
imageProvider: NetworkImage(
|
||||
listData[index],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
//图片张数指示器
|
||||
Positioned(
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 20,
|
||||
child: Container(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
"${currentPage + 1}/${listData.length}",
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
274
lib/upload_image/ossUtil.dart
Executable file
274
lib/upload_image/ossUtil.dart
Executable file
@@ -0,0 +1,274 @@
|
||||
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,
|
||||
}) 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",
|
||||
),
|
||||
});
|
||||
await EasyLoading.show(
|
||||
// status: 'loading...',
|
||||
maskType: EasyLoadingMaskType.black,
|
||||
);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
375
lib/upload_image/upload_image.dart
Normal file
375
lib/upload_image/upload_image.dart
Normal file
@@ -0,0 +1,375 @@
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_common/utils/customer.dart';
|
||||
import 'package:flutter_common/utils/toast_utils.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
// import 'package:images_picker/images_picker.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
import 'ossUtil.dart';
|
||||
|
||||
class UploadImages extends StatefulWidget {
|
||||
final Function? chooseImages; // List<String>
|
||||
final int? max; //最大照片数量
|
||||
final int? hNumber; //一排最大几个
|
||||
final bool? onlyShow; //仅展示,不操作
|
||||
final BoxFit? fit;
|
||||
final List<String>? imagesList; //图片数组
|
||||
final String oSSAccessKeyId;
|
||||
final String policy;
|
||||
final String callback;
|
||||
final String signature;
|
||||
final String ossDirectory;
|
||||
final String ossHost;
|
||||
final Widget carmaWidget;
|
||||
final Function? oneTap; //点击的哪一个
|
||||
final Function? deleteTap; //删除一个后
|
||||
|
||||
const UploadImages({
|
||||
super.key,
|
||||
this.chooseImages,
|
||||
this.max = 9,
|
||||
this.onlyShow = false,
|
||||
this.imagesList,
|
||||
required this.oSSAccessKeyId,
|
||||
required this.policy,
|
||||
required this.callback,
|
||||
required this.signature,
|
||||
required this.ossDirectory,
|
||||
required this.ossHost,
|
||||
required this.carmaWidget,
|
||||
this.hNumber = 3,
|
||||
this.fit,
|
||||
this.oneTap,
|
||||
this.deleteTap,
|
||||
});
|
||||
|
||||
@override
|
||||
State<UploadImages> createState() => _UploadImagesState();
|
||||
}
|
||||
|
||||
class _UploadImagesState extends State<UploadImages> {
|
||||
List<String> imagesList = [];
|
||||
bool isMax = false; //是否达到最大值
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// print("widget.maxwidget.max ============ ${widget.max}");
|
||||
if (widget.imagesList != null) {
|
||||
imagesList = widget.imagesList ?? [];
|
||||
}
|
||||
super.initState();
|
||||
}
|
||||
|
||||
///数组的数量
|
||||
setImageListLength() {
|
||||
// print("widget.maxwidget.max ============ ${widget.max}");
|
||||
// print("imagesList.length ============ ${imagesList.length}");
|
||||
if (imagesList.length < (widget.max?.toInt() ?? 9)) {
|
||||
isMax = false;
|
||||
return imagesList.length + 1;
|
||||
} else if (imagesList.length == (widget.max?.toInt() ?? 9)) {
|
||||
isMax = true;
|
||||
return imagesList.length;
|
||||
} else {
|
||||
isMax = true;
|
||||
return 9;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MasonryGridView.count(
|
||||
padding: const EdgeInsets.only(top: 0),
|
||||
crossAxisCount: 3,
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemCount: setImageListLength(),
|
||||
itemBuilder: (_, int index) {
|
||||
if (isMax == true) {
|
||||
String? imageUrl = imagesList[index];
|
||||
return cellDeleteWidget(
|
||||
index: index,
|
||||
child: GestureDetector(
|
||||
onTap: () => widget.oneTap?.call(index),
|
||||
child: imageNetworkWidget(
|
||||
imageUrl: imageUrl,
|
||||
index: index,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
if (index == setImageListLength() - 1) {
|
||||
return widget.onlyShow == true
|
||||
? const SizedBox()
|
||||
: uploadWidget(context);
|
||||
} else {
|
||||
String? imageUrl = imagesList[index];
|
||||
return cellDeleteWidget(
|
||||
index: index,
|
||||
child: imageNetworkWidget(
|
||||
imageUrl: imageUrl,
|
||||
index: index,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
mainAxisSpacing: 15,
|
||||
crossAxisSpacing: 8,
|
||||
);
|
||||
}
|
||||
|
||||
Widget imageNetworkWidget({
|
||||
required String imageUrl,
|
||||
required int index,
|
||||
}) {
|
||||
return GestureDetector(
|
||||
onTap: () => widget.oneTap?.call(index),
|
||||
child: CustomerImagesNetworking(
|
||||
imageUrl: imageUrl,
|
||||
fit: widget.fit ?? BoxFit.cover,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
///cell 总样式
|
||||
Widget cellWidget({required Widget child}) {
|
||||
return SizedBox(
|
||||
key: Key(cellKeyString()),
|
||||
width: (Get.width - 32 - 32) / (widget.hNumber ?? 3),
|
||||
height: (Get.width - 32 - 32) / (widget.hNumber ?? 3),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
///cell key 随机数+时间
|
||||
String cellKeyString({String? string}) {
|
||||
var random = Random();
|
||||
int randomNumber = random.nextInt(10000); // 生成0到10000000000000之间的随机整数
|
||||
return '$randomNumber + $string + ${DateTime.now().toString()}';
|
||||
}
|
||||
|
||||
///有删除样式的cell
|
||||
Widget cellDeleteWidget({
|
||||
required Widget child,
|
||||
required int index,
|
||||
}) {
|
||||
return Stack(
|
||||
alignment: Alignment.topRight,
|
||||
children: [
|
||||
cellWidget(child: child),
|
||||
widget.onlyShow == true
|
||||
? const SizedBox()
|
||||
: GestureDetector(
|
||||
onTap: () {
|
||||
imagesList.removeAt(index);
|
||||
widget.deleteTap?.call(imagesList);
|
||||
setState(() {});
|
||||
},
|
||||
child: ClipOval(
|
||||
child: Container(
|
||||
width: 30.w,
|
||||
height: 30.w,
|
||||
color: Colors.grey.withOpacity(0.5),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
Icons.close,
|
||||
size: 25.w,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
///上传的Widget
|
||||
Widget uploadWidget(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: () async {
|
||||
if (Platform.isIOS) {
|
||||
await chooseCamera(
|
||||
context: context,
|
||||
max: widget.max,
|
||||
);
|
||||
} else {
|
||||
await chooseCamera(
|
||||
context: context,
|
||||
max: widget.max,
|
||||
);
|
||||
// bool b = await requestPermission(context);
|
||||
// if (b == true) {
|
||||
// await chooseCamera(
|
||||
// context: context,
|
||||
// max: widget.max,
|
||||
// );
|
||||
// }
|
||||
}
|
||||
},
|
||||
child: cellWidget(
|
||||
child: widget.carmaWidget,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 动态申请权限,需要区分android和ios,很多时候它两配置权限时各自的名称不同
|
||||
/// 此处以保存图片需要的配置为例
|
||||
Future<bool> requestPermission(context) async {
|
||||
late PermissionStatus status;
|
||||
// 1、读取系统权限的弹框
|
||||
if (Platform.isIOS) {
|
||||
status = await Permission.photosAddOnly.request();
|
||||
} else {
|
||||
status = await Permission.camera.request();
|
||||
}
|
||||
// 2、假如你点not allow后,下次点击不会在出现系统权限的弹框(系统权限的弹框只会出现一次),
|
||||
// 这时候需要你自己写一个弹框,然后去打开app权限的页面
|
||||
|
||||
if (status != PermissionStatus.granted) {
|
||||
showCupertinoDialog(
|
||||
context: context,
|
||||
builder: (BuildContext ctx) {
|
||||
return CupertinoAlertDialog(
|
||||
title: const Text('您需要去打开权限'),
|
||||
content: const Text('请打开您的相机或者相册权限'),
|
||||
actions: <Widget>[
|
||||
CupertinoDialogAction(
|
||||
child: const Text('取消'),
|
||||
onPressed: () {
|
||||
Navigator.pop(ctx);
|
||||
},
|
||||
),
|
||||
CupertinoDialogAction(
|
||||
child: const Text('确定'),
|
||||
onPressed: () {
|
||||
Navigator.pop(ctx);
|
||||
// 打开手机上该app权限的页面
|
||||
openAppSettings();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
///
|
||||
Future<void> chooseCamera({
|
||||
required BuildContext context,
|
||||
int? max,
|
||||
}) async {
|
||||
//
|
||||
showCupertinoModalPopup(
|
||||
context: context,
|
||||
builder: (BuildContext ctx) {
|
||||
return CupertinoActionSheet(
|
||||
title: const Text('上传图片'),
|
||||
message: Text('请选择上传方式\n相册最多${max ?? 9}张'),
|
||||
actions: <Widget>[
|
||||
CupertinoActionSheetAction(
|
||||
child: const Text('拍照上传'),
|
||||
onPressed: () {
|
||||
openCamera();
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
CupertinoActionSheetAction(
|
||||
child: const Text('相册'),
|
||||
onPressed: () {
|
||||
openGallery();
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
],
|
||||
cancelButton: CupertinoActionSheetAction(
|
||||
isDefaultAction: true,
|
||||
child: const Text('取消'),
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
openCamera() async {
|
||||
XFile? file = await ImagePicker().pickImage(
|
||||
source: ImageSource.camera,
|
||||
);
|
||||
if (file == null) {
|
||||
// Get.back();
|
||||
} else {
|
||||
String imgPath = await saveNetworkImg(
|
||||
file,
|
||||
);
|
||||
imagesList.add(imgPath);
|
||||
widget.chooseImages?.call(imagesList);
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
openGallery() async {
|
||||
int number = (widget.max ?? 9) - imagesList.length;
|
||||
// List<Media>? images =
|
||||
// await ImagesPicker.pick(count: number, pickType: PickType.image);
|
||||
List<String> list = [];
|
||||
List<XFile>? images = await ImagePicker().pickMultiImage(limit: number,);
|
||||
if (images.isEmpty != true) {
|
||||
for (var element in images) {
|
||||
String path = await saveNetworkImgGallery(
|
||||
element.path,
|
||||
);
|
||||
list.add(path);
|
||||
}
|
||||
imagesList.addAll(list);
|
||||
widget.chooseImages?.call(imagesList);
|
||||
setState(() {});
|
||||
} else {
|
||||
ToastUtils.showToast(msg: "请选择图片");
|
||||
}
|
||||
}
|
||||
|
||||
// 保存网络图片
|
||||
Future<String> saveNetworkImg(XFile file) async {
|
||||
// print("file.path ===== ${file.path}");
|
||||
String string = await UploadOss.upload(
|
||||
file.path,
|
||||
fileType: "jpg",
|
||||
oSSAccessKeyId: widget.oSSAccessKeyId,
|
||||
ossHost: widget.ossHost,
|
||||
ossDirectory: widget.ossDirectory,
|
||||
policy: widget.policy,
|
||||
callback: widget.callback,
|
||||
signature: widget.signature,
|
||||
);
|
||||
return string;
|
||||
}
|
||||
|
||||
// 保存网络图片
|
||||
Future<String> saveNetworkImgGallery(String path) async {
|
||||
String string = await UploadOss.upload(
|
||||
path,
|
||||
fileType: "jpg",
|
||||
oSSAccessKeyId: widget.oSSAccessKeyId,
|
||||
ossHost: widget.ossHost,
|
||||
ossDirectory: widget.ossDirectory,
|
||||
policy: widget.policy,
|
||||
callback: widget.callback,
|
||||
signature: widget.signature,
|
||||
);
|
||||
return string;
|
||||
}
|
||||
}
|
||||
341
lib/upload_image/upload_images_tool.dart
Normal file
341
lib/upload_image/upload_images_tool.dart
Normal file
@@ -0,0 +1,341 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_common/upload_image/ossUtil.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
|
||||
// import 'package:images_picker/images_picker.dart';
|
||||
// import 'package:images_picker/images_picker.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
class UploadImagesTool {
|
||||
static uploadImagesTool({
|
||||
String? oSSAccessKeyId,
|
||||
String? policy,
|
||||
String? callback,
|
||||
String? signature,
|
||||
String? ossDirectory,
|
||||
String? ossHost,
|
||||
required BuildContext context,
|
||||
Function? chooseImagesTap,
|
||||
int? max,
|
||||
bool? isVideo,
|
||||
Widget? isAddOtherWidget,
|
||||
}) async {
|
||||
await chooseCamera(
|
||||
context: context,
|
||||
max: max ?? 9,
|
||||
oSSAccessKeyId: oSSAccessKeyId ?? '',
|
||||
ossHost: ossHost ?? '',
|
||||
ossDirectory: ossDirectory ?? '',
|
||||
policy: policy ?? '',
|
||||
callback: callback ?? '',
|
||||
signature: signature ?? '',
|
||||
isVideo: isVideo,
|
||||
isAddOtherWidget: isAddOtherWidget,
|
||||
chooseImages: (list) => chooseImagesTap?.call(list),
|
||||
);
|
||||
}
|
||||
|
||||
/// 动态申请权限,需要区分android和ios,很多时候它两配置权限时各自的名称不同
|
||||
/// 此处以保存图片需要的配置为例
|
||||
static Future<bool> requestPermission(context) async {
|
||||
late PermissionStatus status;
|
||||
// 1、读取系统权限的弹框
|
||||
if (Platform.isIOS) {
|
||||
status = await Permission.photosAddOnly.request();
|
||||
} else {
|
||||
status = await Permission.camera.request();
|
||||
}
|
||||
// 2、假如你点not allow后,下次点击不会在出现系统权限的弹框(系统权限的弹框只会出现一次),
|
||||
// 这时候需要你自己写一个弹框,然后去打开app权限的页面
|
||||
|
||||
if (status != PermissionStatus.granted) {
|
||||
showCupertinoDialog(
|
||||
context: context,
|
||||
builder: (BuildContext ctx) {
|
||||
return CupertinoAlertDialog(
|
||||
title: const Text('您需要去打开权限'),
|
||||
content: const Text('请打开您的相机或者相册权限'),
|
||||
actions: <Widget>[
|
||||
CupertinoDialogAction(
|
||||
child: const Text('取消'),
|
||||
onPressed: () {
|
||||
Navigator.pop(ctx);
|
||||
},
|
||||
),
|
||||
CupertinoDialogAction(
|
||||
child: const Text('确定'),
|
||||
onPressed: () {
|
||||
openAppSettings();
|
||||
Navigator.pop(ctx);
|
||||
// 打开手机上该app权限的页面
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
///
|
||||
static Future<void> chooseCamera({
|
||||
required BuildContext context,
|
||||
int? max,
|
||||
String? oSSAccessKeyId,
|
||||
String? policy,
|
||||
String? callback,
|
||||
String? signature,
|
||||
String? ossDirectory,
|
||||
String? ossHost,
|
||||
Function? chooseImages,
|
||||
bool? isVideo,
|
||||
Widget? isAddOtherWidget,
|
||||
}) async {
|
||||
//
|
||||
showCupertinoModalPopup(
|
||||
context: context,
|
||||
builder: (BuildContext ctx) {
|
||||
return isVideo == true
|
||||
? CupertinoActionSheet(
|
||||
title: const Text('上传视频'),
|
||||
message: Text('请选择视频'),
|
||||
actions: <Widget>[
|
||||
CupertinoActionSheetAction(
|
||||
child: const Text('视频库'),
|
||||
onPressed: () {
|
||||
openGallery(
|
||||
max: max,
|
||||
isVideo: isVideo,
|
||||
oSSAccessKeyId: oSSAccessKeyId ?? '',
|
||||
ossHost: ossHost ?? '',
|
||||
ossDirectory: ossDirectory ?? '',
|
||||
policy: policy ?? '',
|
||||
callback: callback ?? '',
|
||||
signature: signature ?? '',
|
||||
chooseImages: (list) => chooseImages?.call(list),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
],
|
||||
cancelButton: CupertinoActionSheetAction(
|
||||
isDefaultAction: true,
|
||||
child: const Text('取消'),
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
)
|
||||
: CupertinoActionSheet(
|
||||
title: const Text('上传图片'),
|
||||
message: Text('请选择上传方式\n相册最多${max ?? 9}张'),
|
||||
actions: isAddOtherWidget != null
|
||||
? <Widget>[
|
||||
isAddOtherWidget,
|
||||
CupertinoActionSheetAction(
|
||||
child: const Text('拍照上传'),
|
||||
onPressed: () {
|
||||
openCamera(
|
||||
oSSAccessKeyId: oSSAccessKeyId ?? '',
|
||||
ossHost: ossHost ?? '',
|
||||
ossDirectory: ossDirectory ?? '',
|
||||
policy: policy ?? '',
|
||||
callback: callback ?? '',
|
||||
signature: signature ?? '',
|
||||
chooseImages: (list) =>
|
||||
chooseImages?.call(list),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
CupertinoActionSheetAction(
|
||||
child: const Text('相册'),
|
||||
onPressed: () {
|
||||
openGallery(
|
||||
max: max,
|
||||
oSSAccessKeyId: oSSAccessKeyId ?? '',
|
||||
ossHost: ossHost ?? '',
|
||||
ossDirectory: ossDirectory ?? '',
|
||||
policy: policy ?? '',
|
||||
callback: callback ?? '',
|
||||
signature: signature ?? '',
|
||||
chooseImages: (list) =>
|
||||
chooseImages?.call(list),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
]
|
||||
: <Widget>[
|
||||
CupertinoActionSheetAction(
|
||||
child: const Text('拍照上传'),
|
||||
onPressed: () {
|
||||
openCamera(
|
||||
oSSAccessKeyId: oSSAccessKeyId ?? '',
|
||||
ossHost: ossHost ?? '',
|
||||
ossDirectory: ossDirectory ?? '',
|
||||
policy: policy ?? '',
|
||||
callback: callback ?? '',
|
||||
signature: signature ?? '',
|
||||
chooseImages: (list) =>
|
||||
chooseImages?.call(list),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
CupertinoActionSheetAction(
|
||||
child: const Text('相册'),
|
||||
onPressed: () {
|
||||
openGallery(
|
||||
max: max,
|
||||
oSSAccessKeyId: oSSAccessKeyId ?? '',
|
||||
ossHost: ossHost ?? '',
|
||||
ossDirectory: ossDirectory ?? '',
|
||||
policy: policy ?? '',
|
||||
callback: callback ?? '',
|
||||
signature: signature ?? '',
|
||||
chooseImages: (list) =>
|
||||
chooseImages?.call(list),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
],
|
||||
cancelButton: CupertinoActionSheetAction(
|
||||
isDefaultAction: true,
|
||||
child: const Text('取消'),
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
static openCamera({
|
||||
Function? chooseImages,
|
||||
String? oSSAccessKeyId,
|
||||
String? policy,
|
||||
String? callback,
|
||||
String? signature,
|
||||
String? ossDirectory,
|
||||
String? ossHost,
|
||||
}) async {
|
||||
XFile? file = await ImagePicker().pickImage(
|
||||
source: ImageSource.camera,
|
||||
);
|
||||
if (file == null) {
|
||||
Get.back();
|
||||
} else {
|
||||
String imgPath = await saveNetworkImg(
|
||||
file,
|
||||
oSSAccessKeyId: oSSAccessKeyId ?? '',
|
||||
ossHost: ossHost ?? '',
|
||||
ossDirectory: ossDirectory ?? '',
|
||||
policy: policy ?? '',
|
||||
callback: callback ?? '',
|
||||
signature: signature ?? '',
|
||||
);
|
||||
chooseImages?.call([imgPath]);
|
||||
}
|
||||
}
|
||||
|
||||
static openGallery({
|
||||
Function? chooseImages,
|
||||
String? oSSAccessKeyId,
|
||||
String? policy,
|
||||
String? callback,
|
||||
String? signature,
|
||||
String? ossDirectory,
|
||||
String? ossHost,
|
||||
int? max,
|
||||
bool? isVideo,
|
||||
}) async {
|
||||
if (isVideo == true) {
|
||||
XFile? video = await ImagePicker().pickVideo(source: ImageSource.gallery);
|
||||
String path = await saveNetworkImgGallery(
|
||||
video?.path ?? '',
|
||||
fileType: 'mp4',
|
||||
oSSAccessKeyId: oSSAccessKeyId ?? '',
|
||||
ossHost: ossHost ?? '',
|
||||
ossDirectory: ossDirectory ?? '',
|
||||
policy: policy ?? '',
|
||||
callback: callback ?? '',
|
||||
signature: signature ?? '',
|
||||
);
|
||||
chooseImages?.call([path]);
|
||||
print('video path ============ $path');
|
||||
} else {
|
||||
List<XFile>? images = await ImagePicker().pickMultiImage();
|
||||
List<String> list = [];
|
||||
for (var element in images) {
|
||||
String path = await saveNetworkImgGallery(
|
||||
element.path,
|
||||
oSSAccessKeyId: oSSAccessKeyId ?? '',
|
||||
ossHost: ossHost ?? '',
|
||||
ossDirectory: ossDirectory ?? '',
|
||||
policy: policy ?? '',
|
||||
callback: callback ?? '',
|
||||
signature: signature ?? '',
|
||||
);
|
||||
list.add(path);
|
||||
}
|
||||
chooseImages?.call(list);
|
||||
}
|
||||
}
|
||||
|
||||
// 保存网络图片
|
||||
static Future<String> saveNetworkImg(
|
||||
XFile file, {
|
||||
String? oSSAccessKeyId,
|
||||
String? policy,
|
||||
String? callback,
|
||||
String? signature,
|
||||
String? ossDirectory,
|
||||
String? ossHost,
|
||||
}) async {
|
||||
// print("file.path ===== ${file.path}");
|
||||
String string = await UploadOss.upload(
|
||||
file.path,
|
||||
fileType: "jpg",
|
||||
oSSAccessKeyId: oSSAccessKeyId ?? '',
|
||||
ossHost: ossHost ?? '',
|
||||
ossDirectory: ossDirectory ?? '',
|
||||
policy: policy ?? '',
|
||||
callback: callback ?? '',
|
||||
signature: signature ?? '',
|
||||
);
|
||||
// print("Gallery ===string== $string");
|
||||
return string;
|
||||
}
|
||||
|
||||
// 保存网络图片
|
||||
static Future<String> saveNetworkImgGallery(
|
||||
String path, {
|
||||
String? fileType,
|
||||
String? oSSAccessKeyId,
|
||||
String? policy,
|
||||
String? callback,
|
||||
String? signature,
|
||||
String? ossDirectory,
|
||||
String? ossHost,
|
||||
}) async {
|
||||
String string = await UploadOss.upload(
|
||||
path,
|
||||
fileType: fileType ?? "jpg",
|
||||
oSSAccessKeyId: oSSAccessKeyId ?? '',
|
||||
ossHost: ossHost ?? '',
|
||||
ossDirectory: ossDirectory ?? '',
|
||||
policy: policy ?? '',
|
||||
callback: callback ?? '',
|
||||
signature: signature ?? '',
|
||||
);
|
||||
return string;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user