在HarmonyOS(鸿蒙系统)环境下,flutter开发者使用wechat_assets_picker插件进行图片/视频选择时,可能会遇到以下问题:
- 无法正常弹出媒体选择界面
- 选择后无法正确返回文件路径
- 上传功能失效或报错




经过调试每一个环境发现问题处在通过路径访问图片的问题上,鸿蒙不能直接通过uri来读取相册里面的数据,接口返回的uri是一个虚拟的地址。官方文档也有说明。

日志错误信息

然后通过了解wechat_assets_picker的代码结构发现里面和平台相关的一个库flutter_photo_manager,把这库下载到本地,找到ohos平台对应的代码块

这里看到是直接把uri返回了,我们为了能让外界访问path,我们需要做个临时存储空间,为此,特意写了一个文件工具类-FileUtils.ets
import common from '@ohos.app.ability.common';
import fs from '@ohos.file.fs';
import util from '@ohos.util';
import Log from '@ohos/flutter_ohos/src/main/ets/util/Log';
const TAG = "FileUtils";
export default class FileUtils {
static getPathFromUri(context: common.Context | null, uri: string, defExtension?: string) {
Log.i(TAG, "getPathFromUri : " + uri);
let inputFile: fs.File;
try {
inputFile = fs.openSync(uri);
} catch (err) {
Log.e(TAG, "open uri file failed err:" + err)
return null;
}
if (inputFile == null) {
return null;
}
const uuid = util.generateRandomUUID();
if (!context) {
return
}
{
const targetDirectoryPath = context.cacheDir + "/" + uuid;
try {
fs.mkdirSync(targetDirectoryPath);
let targetDir = fs.openSync(targetDirectoryPath);
Log.i(TAG, "mkdirSync success targetDirectoryPath:" + targetDirectoryPath + " fd: " + targetDir.fd);
fs.closeSync(targetDir);
} catch (err) {
Log.e(TAG, "mkdirSync failed err:" + err);
return null;
}
const inputFilePath = uri.substring(uri.lastIndexOf("/") + 1);
const inputFilePathSplits = inputFilePath.split(".");
Log.i(TAG, "getPathFromUri inputFilePath: " + inputFilePath);
const outputFileName = inputFilePathSplits[0];
let extension: string;
if (inputFilePathSplits.length == 2) {
extension = "." + inputFilePathSplits[1];
} else {
if (defExtension) {
extension = defExtension;
} else {
extension = ".jpg";
}
}
const outputFilePath = targetDirectoryPath + "/" + outputFileName + extension;
const outputFile = fs.openSync(outputFilePath, fs.OpenMode.CREATE);
try {
Log.i(TAG, "copyFileSync inputFile fd:" + inputFile.fd + " outputFile fd:" + outputFile.fd);
fs.copyFileSync(inputFile.fd, outputFilePath);
} catch (err) {
Log.e(TAG, "copyFileSync failed err:" + err);
return null;
} finally {
fs.closeSync(inputFile);
fs.closeSync(outputFile);
}
return outputFilePath;
}
}
}
然后引入工具类,把uri转换成缓存路径,返回给dart层
if (photoAsset != null) {
let realPath = FileUtils.getPathFromUri(this.uiContext, photoAsset.uri);
result.success(realPath);
}
引入自己修改后的插件包

先flutter clean 在flutter pub get一下,然后重新运行项目


预览和上传都可以用了,修改后的代码已经开放,地址如下
https://gitcode.com/astevencui/flutter_photo_manager