Skip to content
Toggle navigation
Toggle navigation
This project
Loading...
Sign in
ethan
/
appframe
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
Commit 35706230
authored
2025-12-17 17:55:07 +0800
by
tanghuan
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
微信小程序卡片分享指令处理
1 parent
89a67320
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
158 additions
and
71 deletions
lib/data/repositories/message/choose_file_handler.dart
lib/data/repositories/message/share_handler.dart
lib/utils/image_util.dart
lib/utils/thumbnail_util.dart
lib/utils/video_util.dart
lib/data/repositories/message/choose_file_handler.dart
View file @
3570623
...
...
@@ -3,7 +3,8 @@ import 'dart:io';
import
'package:appframe/config/constant.dart'
;
import
'package:appframe/services/dispatcher.dart'
;
import
'package:appframe/utils/file_type_util.dart'
;
import
'package:appframe/utils/thumbnail_util.dart'
;
import
'package:appframe/utils/image_util.dart'
;
import
'package:appframe/utils/video_util.dart'
;
import
'package:file_picker/file_picker.dart'
;
import
'package:image_size_getter/file_input.dart'
;
import
'package:image_size_getter/image_size_getter.dart'
;
...
...
@@ -64,10 +65,9 @@ class ChooseFileHandler extends MessageHandler {
// 通过image_size_getter获取图片尺寸
var
sizeResult
=
ImageSizeGetter
.
getSizeResult
(
FileInput
(
originalFile
));
var
size
=
sizeResult
.
size
;
imgWidth
=
sizeResult
.
size
.
width
;
imgHeight
=
sizeResult
.
size
.
height
;
final
tempDir
=
await
getTemporaryDirectory
();
imgThumbFilePath
=
await
ThumbnailUtil
.
genTempThumbnail
(
originalFile
,
tempDir
);
imgWidth
=
size
.
width
;
imgHeight
=
size
.
height
;
imgThumbFilePath
=
await
ImageUtil
.
genTempThumbnail
(
originalFile
.
path
);
}
double
?
videoWidth
,
videoHeight
;
...
...
@@ -82,7 +82,8 @@ class ChooseFileHandler extends MessageHandler {
controller
.
dispose
();
final
tempDir
=
await
getTemporaryDirectory
();
videoThumbFilePath
=
await
ThumbnailUtil
.
genVideoThumbnail
(
originalFile
.
path
,
tempDir
);
final
thumbnailPath
=
'
${tempDir.path}
/video_thumb_
${DateTime.now().millisecondsSinceEpoch}
.jpg'
;
videoThumbFilePath
=
await
VideoUtil
.
genVideoThumbnail
(
originalFile
.
path
,
thumbnailPath
);
}
// 返回临时文件信息
...
...
lib/data/repositories/message/share_handler.dart
View file @
3570623
import
'dart:io'
;
import
'package:appframe/config/locator.dart'
;
import
'package:appframe/services/dispatcher.dart'
;
import
'package:appframe/utils/image_util.dart'
;
import
'package:dio/dio.dart'
;
import
'package:fluwx/fluwx.dart'
;
import
'package:path/path.dart'
as
path
;
import
'package:path_provider/path_provider.dart'
;
class
ShareHandler
extends
MessageHandler
{
@override
...
...
@@ -9,17 +15,43 @@ class ShareHandler extends MessageHandler {
throw
Exception
(
'参数错误'
);
}
var
weapp
=
params
[
'weapp'
]
as
Map
<
String
,
dynamic
>?;
var
weapp
=
params
[
'weapp'
];
if
(
weapp
is
!
Map
<
String
,
dynamic
>)
{
throw
Exception
(
'参数错误'
);
}
var
title
=
weapp
[
'title'
]
as
String
?
??
''
;
var
imageUrl
=
weapp
[
'imageUrl'
]
as
String
?
??
''
;
var
path
=
weapp
[
'path'
]
as
String
?
??
''
;
var
appid
=
weapp
[
'appid'
]
as
String
?
??
''
;
var
desc
=
weapp
[
'desc'
]
as
String
?
??
''
;
var
envVersion
=
weapp
[
'envVersion'
]
as
String
?
??
''
;
if
(
title
.
isEmpty
||
imageUrl
.
isEmpty
||
path
.
isEmpty
||
appid
.
isEmpty
)
{
throw
Exception
(
'参数错误'
);
}
// 1 将图片下载到本机
var
imagePath
=
await
_downloadToTemporaryDirectory
(
imageUrl
);
// 2 对图片生成缩略图
// 微信官方要求小程序卡片缩略图数据不能大于 128K,否则分享失败,因此要生成缩略图处理
var
thumbPath
=
await
ImageUtil
.
genTempThumbnail
(
imagePath
,
width:
640
,
quality:
14
);
// 3 读取缩略图为Uint8List
var
thumbData
=
await
File
(
thumbPath
!).
readAsBytes
();
try
{
var
model
=
WeChatShareMiniProgramModel
(
webPageUrl:
imageUrl
,
miniProgramType:
_getWXMiniProgramType
(
envVersion
),
userName:
appid
,
path:
path
,
title:
title
,
description:
desc
,
thumbData:
thumbData
,
);
Fluwx
fluwx
=
getIt
.
get
<
Fluwx
>();
return
await
fluwx
.
share
(
WeChatShareMiniProgramModel
(
title:
weapp
?[
'title'
]
as
String
,
webPageUrl:
weapp
?[
'imageUrl'
]
as
String
,
path:
weapp
?[
'path'
]
as
String
,
userName:
weapp
?[
'appid'
]
as
String
,
miniProgramType:
_getWXMiniProgramType
(
weapp
?[
'envVersion'
]
as
String
?),
));
return
await
fluwx
.
share
(
model
);
}
catch
(
e
)
{
print
(
e
);
return
false
;
...
...
@@ -38,4 +70,31 @@ class ShareHandler extends MessageHandler {
return
WXMiniProgramType
.
preview
;
}
}
///
/// 将http资源下载到临时目录
/// 返回下载后的路径
///
Future
<
String
>
_downloadToTemporaryDirectory
(
String
url
)
async
{
// 要保存的文件名和扩展名
String
saveFileName
=
path
.
basenameWithoutExtension
(
url
);
String
ext
=
path
.
extension
(
url
);
// 临时目录
var
dir
=
await
getTemporaryDirectory
();
// 要保存的路径
var
targetPath
=
path
.
join
(
dir
.
path
,
'
$saveFileName
.
$ext
'
);
// 如果文件存在,则在文件名后添加数字
int
i
=
1
;
while
(
File
(
targetPath
).
existsSync
())
{
targetPath
=
path
.
join
(
dir
.
path
,
'
$saveFileName
(
$i
).
$ext
'
);
i
++;
}
final
resp
=
await
Dio
().
download
(
url
,
targetPath
);
if
(
resp
.
statusCode
!=
200
)
{
throw
Exception
(
'文件下载失败'
);
}
return
targetPath
;
}
}
lib/utils/image_util.dart
0 → 100644
View file @
3570623
import
'dart:io'
;
import
'package:ffmpeg_kit_flutter_new/ffmpeg_kit.dart'
;
import
'package:ffmpeg_kit_flutter_new/return_code.dart'
;
import
'package:path_provider/path_provider.dart'
;
class
ImageUtil
{
/// 使用 ffmpeg_kit_flutter_new 生成指定图片的缩略图
///
/// [imagePath] 原始图片路径
/// [width] 缩略图宽度,默认值为320
/// [quality] JPEG 输出质量 (1-32,数值越小质量越高),默认值为18
/// 返回缩略图路径
static
Future
<
String
?>
genTempThumbnail
(
String
imagePath
,
{
int
width
=
320
,
int
quality
=
18
})
async
{
try
{
// 检查源文件是否存在
final
imageFile
=
File
(
imagePath
);
if
(!
await
imageFile
.
exists
())
{
print
(
'源图片文件不存在:
$imagePath
'
);
return
null
;
}
// 创建临时文件路径用于存储缩略图
final
tempDir
=
await
getTemporaryDirectory
();
final
thumbnailPath
=
'
${tempDir.path}
/thumb_
${DateTime.now().millisecondsSinceEpoch}
.jpg'
;
// 使用 FFmpeg 生成缩略图
// 构建 FFmpeg 命令行参数
String
cmd
=
'-i "
$imagePath
" '
// 指定输入文件路径
'-vf scale=
$width
:-1:flags=lanczos '
// 设置缩略图宽度,高度等比缩放,使用 Lanczos 算法提高质量
'-q:v
$quality
'
// 设置 JPEG 输出质量 (1-32,数值越小质量越高)
'-y '
// 覆盖已存在的输出文件
// '-pix_fmt yuvj420p ' // 指定像素格式以提高兼容性
'"
$thumbnailPath
"'
;
// 指定输出文件路径
// 执行 FFmpeg 命令
final
session
=
await
FFmpegKit
.
execute
(
cmd
);
final
returnCode
=
await
session
.
getReturnCode
();
// 检查执行结果
if
(
ReturnCode
.
isSuccess
(
returnCode
))
{
return
thumbnailPath
;
}
else
{
print
(
'生成图片缩略图失败:
${await session.getFailStackTrace()}
'
);
return
null
;
}
}
catch
(
e
)
{
print
(
'生成图片缩略图出错:
$e
'
);
return
null
;
}
}
}
lib/utils/thumbnail_util.dart
deleted
100644 → 0
View file @
89a6732
import
'dart:io'
;
import
'package:ffmpeg_kit_flutter_new/ffmpeg_kit.dart'
;
import
'package:ffmpeg_kit_flutter_new/return_code.dart'
;
import
'package:flutter_image_compress/flutter_image_compress.dart'
;
/// 缩略图工具类
///
class
ThumbnailUtil
{
/// 在指定目录下生成缩略图
/// 返回缩略图路径
static
Future
<
String
?>
genTempThumbnail
(
File
imageFile
,
Directory
dir
)
async
{
try
{
// 缩略图路径
final
tempPath
=
dir
.
path
;
final
targetPath
=
'
$tempPath
/thumbnail_
${DateTime.now().millisecondsSinceEpoch}
.jpg'
;
// 压缩生成缩略图文件
final
compressedFile
=
await
FlutterImageCompress
.
compressAndGetFile
(
imageFile
.
absolute
.
path
,
targetPath
);
return
compressedFile
!.
path
;
}
catch
(
e
)
{
print
(
'生成缩略图出错:
$e
'
);
return
null
;
}
}
/// 为视频文件生成缩略图
/// 返回缩略图路径
static
Future
<
String
?>
genVideoThumbnail
(
String
videoPath
,
Directory
dir
)
async
{
try
{
final
thumbnailPath
=
'
${dir.path}
/video_thumb_
${DateTime.now().millisecondsSinceEpoch}
.jpg'
;
// 使用 ffmpeg_kit_flutter_new 生成视频缩略图
// 构建FFmpeg命令行参数
String
cmd
=
'-i "
$videoPath
" '
// 指定输入文件路径
'-ss 1 '
// 从视频第1秒处截取画面
'-vframes 1 '
// 只截取一帧画面
'-vf scale=128:-1 '
// 设置缩略图宽度为128像素,高度按比例缩放
'-y '
// 覆盖已存在的输出文件
'"
$thumbnailPath
"'
;
// 指定输出文件路径
final
session
=
await
FFmpegKit
.
execute
(
cmd
);
final
returnCode
=
await
session
.
getReturnCode
();
if
(
ReturnCode
.
isSuccess
(
returnCode
))
{
return
thumbnailPath
;
}
else
{
print
(
'生成视频缩略图失败:
${await session.getFailStackTrace()}
'
);
return
null
;
}
}
catch
(
e
)
{
print
(
'生成视频缩略图出错:
$e
'
);
return
null
;
}
}
}
lib/utils/video_util.dart
View file @
3570623
...
...
@@ -68,4 +68,36 @@ class VideoUtil {
final
returnCode
=
await
session
.
getReturnCode
();
return
ReturnCode
.
isSuccess
(
returnCode
);
}
/// 为视频文件生成缩略图
/// [videoPath] 要生成缩略图的视频文件路径
/// [thumbnailPath] 要生成的缩略图文件路径
/// 返回缩略图路径
static
Future
<
String
?>
genVideoThumbnail
(
String
videoPath
,
String
thumbnailPath
)
async
{
try
{
// final thumbnailPath = '${dir.path}/video_thumb_${DateTime.now().millisecondsSinceEpoch}.jpg';
// 使用 ffmpeg_kit_flutter_new 生成视频缩略图
// 构建FFmpeg命令行参数
String
cmd
=
'-i "
$videoPath
" '
// 指定输入文件路径
'-ss 1 '
// 从视频第1秒处截取画面
'-vframes 1 '
// 只截取一帧画面
'-vf scale=128:-1 '
// 设置缩略图宽度为128像素,高度按比例缩放
'-y '
// 覆盖已存在的输出文件
'"
$thumbnailPath
"'
;
// 指定输出文件路径
final
session
=
await
FFmpegKit
.
execute
(
cmd
);
final
returnCode
=
await
session
.
getReturnCode
();
if
(
ReturnCode
.
isSuccess
(
returnCode
))
{
return
thumbnailPath
;
}
else
{
print
(
'生成视频缩略图失败:
${await session.getFailStackTrace()}
'
);
return
null
;
}
}
catch
(
e
)
{
print
(
'生成视频缩略图出错:
$e
'
);
return
null
;
}
}
}
Write
Preview
Styling with
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment