Flutter URI转换文件插件uri_to_file的使用
Flutter URI转换文件插件uri_to_file的使用
uri_to_file
uri_to_file
是一个Flutter插件,用于将支持的URI转换为文件。它支持Android和iOS平台。
支持的Uri Schema
content://
(仅限Android)File.fromUri(uri)
支持的Schema
开始使用
添加依赖
在项目的pubspec.yaml
文件中添加以下依赖:
dependencies:
uri_to_file: ^1.0.0
使用方法
下面是一个简单的示例,演示如何将URI转换为文件:
import 'dart:io';
import 'package:uri_to_file/uri_to_file.dart';
Future<void> convertUriToFile() async {
try {
String uriString = 'content://sample.txt'; // Uri string
// 不要通过 uri.toString() 传递 Uri 对象作为参数。
// 因为 uri.toString() 会将字符串转换为小写,这会导致此包行为异常
// 如果你正在使用 uni_links 包进行深度链接。
// 请使用 getInitialLink() 或 linkStream 传递 Uri 字符串
File file = await toFile(uriString); // 将 uri 转换为文件
print('文件路径:${file.path}');
} catch (e) {
print(e); // 异常
}
}
重要提示
- 不要通过
uri.toString()
传递 Uri 对象作为参数。因为uri.toString()
会将字符串转换为小写,这会导致此包行为异常。 - 如果你正在使用
uni_links
包进行深度链接,请使用getInitialLink()
或linkStream
传递 Uri 字符串。 - 查看完整示例:https://pub.dev/packages/uri_to_file/example
完整示例demo
下面是一个完整的示例应用程序,展示了如何处理从其他应用打开的文件并将其URI转换为文件。
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:path/path.dart';
import 'package:uri_to_file/uri_to_file.dart';
import 'package:uni_links/uni_links.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await clearTemporaryFiles();
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool _isLoading = false, _hasError = false;
File? _file;
@override
void initState() {
init();
super.initState();
}
/// 初始化
void init() {
_processInitialUri();
_listenForUri();
}
/// 获取初始 Uri
Future<void> _processInitialUri() async {
String? uriString = await getInitialLink();
_processUri(uriString);
}
/// 监听 Uri
void _listenForUri() {
linkStream.listen((uriString) => _processUri(uriString));
}
/// 处理 Uri
Future<void> _processUri(String? uriString) async {
try {
if (uriString != null) {
_hasError = false;
_isLoading = true;
setState(() {});
_file = await toFile(uriString);
_isLoading = false;
setState(() {});
}
} catch (e) {
Fluttertoast.showToast(msg: 'Something went wrong. Please try again');
_hasError = true;
print(e.toString());
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Uri To File Example'),
),
body: Container(
padding: const EdgeInsets.all(16.0),
child: _body(),
),
),
);
}
Widget _body() {
return Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_getStepsInfo(),
_getFileDetails(),
],
);
}
Widget _getStepsInfo() {
return const Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Note:',
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'-',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
),
Expanded(
child: Text(
'Open any file from file browser app or any other app and select uri_to_file_example app.',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
),
),
],
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'-',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
),
Expanded(
child: Text(
'File opened from file browser app or any other app.\nIt contains content:// uri.',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
),
),
],
),
],
);
}
Widget _getFileDetails() {
return Expanded(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const Row(
children: [
Expanded(
child: Text(
'Opened',
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
),
),
],
),
const Row(
children: [
Expanded(
child: Text(
'File Name',
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
),
),
],
),
_getFileName(),
],
),
);
}
Widget _getFileName() {
if (_isLoading) {
return Container(
margin: const EdgeInsets.only(top: 8.0),
child: const SizedBox(
width: 16.0,
height: 16.0,
child: CircularProgressIndicator(
strokeWidth: 3.0,
),
),
);
}
if (_file != null) {
return Row(
children: [
Expanded(
child: Text(
basename(_file!.path),
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
),
],
);
}
return Row(
children: [
Expanded(
child: Text(
(_hasError) ? 'Error' : 'N/A',
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
),
],
);
}
}
工作原理
- content:// (仅限Android)
uri_to_file
使用原生通道创建一个临时文件,并将其存储在应用程序目录中。 - 其他 URI
其他 URI 由 Flutter SDK 自身通过File.fromUri(uri)
处理。
许可证
MIT License
功能和Bug
请在 GitHub Issues 中提交功能请求和Bug报告。
希望这个详细的说明和示例代码能帮助你更好地理解和使用 uri_to_file
插件!如果有任何问题或需要进一步的帮助,请随时提问。
更多关于Flutter URI转换文件插件uri_to_file的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter URI转换文件插件uri_to_file的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用uri_to_file
插件的示例代码。这个插件可以将URI转换为文件路径,非常适用于处理从其他应用接收到的内容URI(如从文件选择器获取的文件)。
首先,确保在你的pubspec.yaml
文件中添加uri_to_file
依赖:
dependencies:
flutter:
sdk: flutter
uri_to_file: ^x.y.z # 请替换为最新版本号
然后,运行flutter pub get
来安装依赖。
接下来,你可以在你的Flutter应用中这样使用uri_to_file
插件:
import 'package:flutter/material.dart';
import 'package:uri_to_file/uri_to_file.dart';
import 'package:path_provider/path_provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('URI to File Example'),
),
body: UriToFileExample(),
),
);
}
}
class UriToFileExample extends StatefulWidget {
@override
_UriToFileExampleState createState() => _UriToFileExampleState();
}
class _UriToFileExampleState extends State<UriToFileExample> {
String? filePath;
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Converted File Path:'),
Text(filePath ?? 'N/A', style: TextStyle(fontSize: 18)),
SizedBox(height: 20),
ElevatedButton(
onPressed: _pickFileAndConvertUri,
child: Text('Pick File and Convert URI'),
),
],
),
);
}
Future<void> _pickFileAndConvertUri() async {
// Here you would typically use a file picker plugin to get a URI.
// For simplicity, let's assume we have a sample URI.
// In reality, you would replace this URI with the one obtained from the file picker.
String sampleUri = "content://com.example.provider/external_files/sample.txt";
try {
// Convert URI to file path
File file = await UriToFile.convertToFilePath(Uri.parse(sampleUri));
setState(() {
filePath = file.path;
});
} catch (e) {
print("Error converting URI to file path: $e");
// Handle the error appropriately
}
}
}
注意:
- 上述代码假设你已经有一个内容URI(例如从文件选择器获取的URI)。在真实应用中,你需要使用文件选择器插件(如
file_picker
)来获取用户选择的文件的URI。 - 由于Android的权限和文件访问限制,某些URI可能需要额外的权限或内容访问提供者才能成功转换为文件路径。
- 如果你的应用需要处理敏感或私有文件,请确保遵循最佳实践和Android/iOS的安全指导。
文件选择器插件示例(如果需要):
你可以使用file_picker
插件来获取文件URI,如下所示:
dependencies:
file_picker: ^x.y.z # 请替换为最新版本号
然后在你的代码中使用file_picker
来选择文件并获取URI:
import 'package:file_picker/file_picker.dart';
// 在你的_UriToFileExampleState类中
Future<void> _pickFile() async {
FilePickerResult? result = await FilePicker.platform.pickFiles();
if (result != null && result.files.isNotEmpty) {
FilePickerFile file = result.files.first;
// 获取文件URI
String fileUri = file.path; // 在Android上这是URI,在iOS上这是文件路径
// 根据平台不同处理URI或路径
if (Platform.isAndroid) {
// 对于Android,file.path是一个内容URI
try {
File convertedFile = await UriToFile.convertToFilePath(Uri.parse(fileUri));
setState(() {
filePath = convertedFile.path;
});
} catch (e) {
print("Error converting URI to file path: $e");
}
} else if (Platform.isIOS) {
// 对于iOS,file.path已经是一个文件路径
setState(() {
filePath = fileUri;
});
}
}
}
确保根据文件选择器返回的URI类型进行适当的处理。