Files
flutter_common/lib/upload_image/upload_images_tool.dart
T

499 lines
16 KiB
Dart

import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter_common/upload_image/ossUtil.dart';
import 'package:flutter_image_compress/flutter_image_compress.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';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
class _CompressedImageFile {
const _CompressedImageFile({
required this.path,
required this.fileType,
});
final String path;
final String fileType;
}
class _ImageCompressionTarget {
const _ImageCompressionTarget({
required this.format,
required this.extension,
required this.fileType,
});
final CompressFormat format;
final String extension;
final String fileType;
}
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,
bool? isShowLoading,
}) async {
await chooseCamera(
context: context,
max: max,
oSSAccessKeyId: oSSAccessKeyId ?? '',
ossHost: ossHost ?? '',
ossDirectory: ossDirectory ?? '',
policy: policy ?? '',
callback: callback ?? '',
signature: signature ?? '',
isVideo: isVideo,
isAddOtherWidget: isAddOtherWidget,
isShowLoading: isShowLoading,
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,
bool? isShowLoading,
}) 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: (max == null || max == 0)
? null
: Text('请选择上传方式\n相册最多$max张'),
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 ?? '',
isShowLoading: isShowLoading,
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,
maxHeight: 1080,
maxWidth: 1920,
imageQuality: 80);
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,
bool? isShowLoading,
}) async {
if (isVideo == true) {
final List<AssetEntity>? result = await AssetPicker.pickAssets(
Get.context!,
pickerConfig:
AssetPickerConfig(maxAssets: 1, requestType: RequestType.video),
);
final File? video = await result?.first.file;
String path = await saveNetworkImgGallery(
video?.path ?? '',
fileType: 'mp4',
oSSAccessKeyId: oSSAccessKeyId ?? '',
ossHost: ossHost ?? '',
ossDirectory: ossDirectory ?? '',
policy: policy ?? '',
callback: callback ?? '',
signature: signature ?? '',
);
chooseImages?.call([path]);
} else {
/// 创建临时目录
final Directory tempDir =
Directory.systemTemp.createTempSync('compressed_images_');
final List<AssetEntity>? result = await AssetPicker.pickAssets(
Get.context!,
pickerConfig: AssetPickerConfig(maxAssets: max ?? 50),
);
/// 临时存储选中的图片
final List<_CompressedImageFile> selectedFiles = [];
if (result != null && result.isNotEmpty) {
for (int i = 0; i < result.length; i++) {
final File? file = await result[i].file;
if (file != null) {
final _CompressedImageFile? compressedFile =
await _compressGalleryImage(file, tempDir);
if (compressedFile != null) {
selectedFiles.add(compressedFile);
}
}
}
}
/// 上传选中的图片
List<String> list = [];
for (var element in selectedFiles) {
String path = await saveNetworkImgGallery(
element.path,
fileType: element.fileType,
oSSAccessKeyId: oSSAccessKeyId ?? '',
ossHost: ossHost ?? '',
ossDirectory: ossDirectory ?? '',
policy: policy ?? '',
callback: callback ?? '',
signature: signature ?? '',
isShowLoading: isShowLoading,
);
list.add(path);
}
chooseImages?.call(list);
}
}
static Future<_CompressedImageFile?> _compressGalleryImage(
File file,
Directory tempDir,
) async {
final _ImageCompressionTarget target =
_compressionTargetForPath(file.absolute.path);
final XFile? compressedFile = await _compressImageWithTarget(
file,
tempDir,
target,
);
if (compressedFile != null) {
return _CompressedImageFile(
path: compressedFile.path,
fileType: target.fileType,
);
}
if (target.format == CompressFormat.jpeg) {
return null;
}
const _ImageCompressionTarget fallbackTarget = _ImageCompressionTarget(
format: CompressFormat.jpeg,
extension: 'jpg',
fileType: 'jpg',
);
final XFile? fallbackFile = await _compressImageWithTarget(
file,
tempDir,
fallbackTarget,
);
if (fallbackFile == null) {
return null;
}
return _CompressedImageFile(
path: fallbackFile.path,
fileType: fallbackTarget.fileType,
);
}
static Future<XFile?> _compressImageWithTarget(
File file,
Directory tempDir,
_ImageCompressionTarget target,
) async {
try {
return await FlutterImageCompress.compressAndGetFile(
file.absolute.path,
'${tempDir.path}/${DateTime.now().microsecondsSinceEpoch}_compressed.${target.extension}',
quality: 80,
minWidth: 1920,
minHeight: 1080,
format: target.format,
);
} catch (_) {
return null;
}
}
static _ImageCompressionTarget _compressionTargetForPath(String path) {
final String extension =
path.split('?').first.split('.').last.toLowerCase();
switch (extension) {
case 'png':
return const _ImageCompressionTarget(
format: CompressFormat.png,
extension: 'png',
fileType: 'png',
);
case 'webp':
return const _ImageCompressionTarget(
format: CompressFormat.webp,
extension: 'webp',
fileType: 'webp',
);
case 'heic':
case 'heif':
return const _ImageCompressionTarget(
format: CompressFormat.heic,
extension: 'heic',
fileType: 'heic',
);
case 'jpeg':
case 'jpg':
default:
return const _ImageCompressionTarget(
format: CompressFormat.jpeg,
extension: 'jpg',
fileType: 'jpg',
);
}
}
// 保存网络图片
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,
bool? isShowLoading,
}) async {
String string = await UploadOss.upload(
path,
fileType: fileType ?? "jpg",
oSSAccessKeyId: oSSAccessKeyId ?? '',
ossHost: ossHost ?? '',
ossDirectory: ossDirectory ?? '',
policy: policy ?? '',
callback: callback ?? '',
signature: signature ?? '',
isShowLoading: isShowLoading,
);
return string;
}
}