fix:优化图片上传组件,解决png图片报错问题
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_common/upload_image/ossUtil.dart';
|
||||
@@ -12,6 +11,28 @@ import 'package:image_picker/image_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,
|
||||
@@ -139,7 +160,9 @@ class UploadImagesTool {
|
||||
)
|
||||
: CupertinoActionSheet(
|
||||
title: const Text('上传图片'),
|
||||
message: (max == null || max == 0) ? null : Text('请选择上传方式\n相册最多${max}张'),
|
||||
message: (max == null || max == 0)
|
||||
? null
|
||||
: Text('请选择上传方式\n相册最多$max张'),
|
||||
actions: isAddOtherWidget != null
|
||||
? <Widget>[
|
||||
isAddOtherWidget,
|
||||
@@ -153,7 +176,8 @@ class UploadImagesTool {
|
||||
policy: policy ?? '',
|
||||
callback: callback ?? '',
|
||||
signature: signature ?? '',
|
||||
chooseImages: (list) => chooseImages?.call(list),
|
||||
chooseImages: (list) =>
|
||||
chooseImages?.call(list),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
@@ -169,7 +193,8 @@ class UploadImagesTool {
|
||||
policy: policy ?? '',
|
||||
callback: callback ?? '',
|
||||
signature: signature ?? '',
|
||||
chooseImages: (list) => chooseImages?.call(list),
|
||||
chooseImages: (list) =>
|
||||
chooseImages?.call(list),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
@@ -186,7 +211,8 @@ class UploadImagesTool {
|
||||
policy: policy ?? '',
|
||||
callback: callback ?? '',
|
||||
signature: signature ?? '',
|
||||
chooseImages: (list) => chooseImages?.call(list),
|
||||
chooseImages: (list) =>
|
||||
chooseImages?.call(list),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
@@ -203,7 +229,8 @@ class UploadImagesTool {
|
||||
callback: callback ?? '',
|
||||
signature: signature ?? '',
|
||||
isShowLoading: isShowLoading,
|
||||
chooseImages: (list) => chooseImages?.call(list),
|
||||
chooseImages: (list) =>
|
||||
chooseImages?.call(list),
|
||||
);
|
||||
Get.back();
|
||||
},
|
||||
@@ -231,11 +258,10 @@ class UploadImagesTool {
|
||||
String? ossHost,
|
||||
}) async {
|
||||
XFile? file = await ImagePicker().pickImage(
|
||||
source: ImageSource.camera,
|
||||
maxHeight: 1080,
|
||||
maxWidth: 1920,
|
||||
imageQuality: 80
|
||||
);
|
||||
source: ImageSource.camera,
|
||||
maxHeight: 1080,
|
||||
maxWidth: 1920,
|
||||
imageQuality: 80);
|
||||
if (file == null) {
|
||||
Get.back();
|
||||
} else {
|
||||
@@ -267,7 +293,8 @@ class UploadImagesTool {
|
||||
if (isVideo == true) {
|
||||
final List<AssetEntity>? result = await AssetPicker.pickAssets(
|
||||
Get.context!,
|
||||
pickerConfig: AssetPickerConfig(maxAssets: 1, requestType: RequestType.video),
|
||||
pickerConfig:
|
||||
AssetPickerConfig(maxAssets: 1, requestType: RequestType.video),
|
||||
);
|
||||
final File? video = await result?.first.file;
|
||||
String path = await saveNetworkImgGallery(
|
||||
@@ -283,34 +310,34 @@ class UploadImagesTool {
|
||||
chooseImages?.call([path]);
|
||||
} else {
|
||||
/// 创建临时目录
|
||||
final Directory tempDir = Directory.systemTemp.createTempSync('compressed_images_');
|
||||
final Directory tempDir =
|
||||
Directory.systemTemp.createTempSync('compressed_images_');
|
||||
final List<AssetEntity>? result = await AssetPicker.pickAssets(
|
||||
Get.context!,
|
||||
pickerConfig: AssetPickerConfig(maxAssets: max ?? 50),
|
||||
);
|
||||
|
||||
/// 临时存储选中的图片
|
||||
final List<XFile> selectedFiles = [];
|
||||
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 String extension = file.absolute.path.split('.').last;
|
||||
/// 压缩并保存到临时文件
|
||||
final XFile? compressedFile = await FlutterImageCompress.compressAndGetFile(
|
||||
file.absolute.path, '${tempDir.path}/${DateTime.now().millisecondsSinceEpoch}_compressed.$extension',
|
||||
quality: 80, minWidth: 1920, minHeight: 1080);
|
||||
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 ?? '',
|
||||
@@ -325,6 +352,99 @@ class UploadImagesTool {
|
||||
}
|
||||
}
|
||||
|
||||
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, {
|
||||
|
||||
Reference in New Issue
Block a user