Flutter图片下载插件image_downloader的使用
Flutter图片下载插件image_downloader的使用
image_downloader
是一个用于Flutter应用中下载网络图片和视频并保存到相册(iOS)或指定目录(Android)的插件。它能够保留Exif(DateTimeOriginal)和GPS(Latitude, Longitude)信息。
开始使用
iOS配置
在你的 Info.plist
文件中添加以下键:
- NSPhotoLibraryUsageDescription:说明你的应用为什么需要访问用户的相册。
- NSPhotoLibraryAddUsageDescription:说明你的应用为什么需要获取写入用户相册的权限。
Android配置
如果你调用了 AndroidDestinationType#inExternalFilesDir()
,则不需要额外权限。否则,在 AndroidManifest.xml
中添加如下权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
此外,如果你想使用预览功能,则需要在 <application>
标签内添加 provider 配置,并创建 provider_paths.xml
文件。
<provider
android:name="com.ko2ic.imagedownloader.FileProvider"
android:authorities="${applicationId}.image_downloader.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
</provider>
provider_paths.xml
内容如下:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
</paths>
示例代码
下面是一个完整的示例,展示了如何使用 image_downloader
插件来下载图片、处理进度更新以及展示下载结果。
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_downloader/image_downloader.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String _message = "";
String _path = "";
String _size = "";
String _mimeType = "";
File? _imageFile;
int _progress = 0;
List<File> _multipleFiles = [];
@override
void initState() {
super.initState();
// 设置进度回调
ImageDownloader.callback(onProgressUpdate: (String? imageId, int progress) {
setState(() {
_progress = progress;
});
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Image Downloader Example'),
),
body: Center(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('Progress: $_progress %'),
Text(_message),
Text(_size),
Text(_mimeType),
Text(_path),
if (_path.isNotEmpty)
ElevatedButton(
onPressed: () async {
await ImageDownloader.open(_path).catchError((error) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text((error as PlatformException).message ?? ''),
));
});
},
child: Text("Open"),
),
ElevatedButton(
onPressed: () {
ImageDownloader.cancel();
},
child: Text("Cancel"),
),
ElevatedButton(
onPressed: () {
_downloadImage(
"https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/bigsize.jpg");
},
child: Text("Default Destination"),
),
ElevatedButton(
onPressed: () {
_downloadImage(
"https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter.png",
destination: AndroidDestinationType.directoryPictures
..inExternalFilesDir()
..subDirectory("sample.gif"),
);
},
child: Text("Custom Destination (only Android)"),
),
ElevatedButton(
onPressed: () {
_downloadImage(
"https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter_no.png",
whenError: true);
},
child: Text("404 Error"),
),
ElevatedButton(
onPressed: () {
_downloadImage(
"https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/sample.mkv",
whenError: true);
},
child: Text("Unsupported File Error (only iOS)"),
),
ElevatedButton(
onPressed: () {
_downloadImage(
"https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/sample.mov");
},
child: Text("Movie"),
),
ElevatedButton(
onPressed: () async {
var list = [
"https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/bigsize.jpg",
"https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter.jpg",
"https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter_transparent.png",
"https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter_no.png",
"https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/flutter.png",
];
List<File> files = [];
for (var url in list) {
try {
final imageId = await ImageDownloader.downloadImage(url);
final path = await ImageDownloader.findPath(imageId!);
files.add(File(path!));
} catch (error) {
print(error);
}
}
setState(() {
_multipleFiles.addAll(files);
});
},
child: Text("Multiple Download"),
),
ElevatedButton(
onPressed: () => _downloadImage(
"https://raw.githubusercontent.com/wiki/ko2ic/image_downloader/images/sample.webp",
outputMimeType: "image/png",
),
child: Text("Download WebP (only Android)"),
),
if (_imageFile != null) Image.file(_imageFile!),
GridView.count(
crossAxisCount: 4,
shrinkWrap: true,
physics: BouncingScrollPhysics(),
children: List.generate(_multipleFiles.length, (index) {
return SizedBox(
width: 50,
height: 50,
child: Image.file(File(_multipleFiles[index].path)),
);
}),
),
],
),
),
),
),
);
}
Future<void> _downloadImage(
String url, {
AndroidDestinationType? destination,
bool whenError = false,
String? outputMimeType,
}) async {
String? fileName;
String? path;
int? size;
String? mimeType;
try {
String? imageId;
if (whenError) {
imageId = await ImageDownloader.downloadImage(url,
outputMimeType: outputMimeType)
.catchError((error) {
if (error is PlatformException) {
String? path = "";
if (error.code == "404") {
print("Not Found Error.");
} else if (error.code == "unsupported_file") {
print("UnSupported FIle Error.");
path = error.details["unsupported_file_path"];
}
setState(() {
_message = error.toString();
_path = path ?? '';
});
}
print(error);
}).timeout(Duration(seconds: 10), onTimeout: () {
print("timeout");
return;
});
} else {
if (destination == null) {
imageId = await ImageDownloader.downloadImage(
url,
outputMimeType: outputMimeType,
);
} else {
imageId = await ImageDownloader.downloadImage(
url,
destination: destination,
outputMimeType: outputMimeType,
);
}
}
if (imageId == null) {
return;
}
fileName = await ImageDownloader.findName(imageId);
path = await ImageDownloader.findPath(imageId);
size = await ImageDownloader.findByteSize(imageId);
mimeType = await ImageDownloader.findMimeType(imageId);
} on PlatformException catch (error) {
setState(() {
_message = error.message ?? '';
});
return;
}
if (!mounted) return;
setState(() {
var location = Platform.isAndroid ? "Directory" : "Photo Library";
_message = 'Saved as "$fileName" in $location.\n';
_size = 'size: $size';
_mimeType = 'mimeType: $mimeType';
_path = path ?? '';
if (!_mimeType.contains("video")) {
_imageFile = File(path!);
}
return;
});
}
}
这个示例应用程序提供了多个按钮来触发不同类型的图片下载操作,并且可以在界面上显示下载进度、文件信息以及下载完成后的图片预览。通过这种方式,你可以更好地理解和使用 image_downloader
插件的功能。
更多关于Flutter图片下载插件image_downloader的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter图片下载插件image_downloader的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用image_downloader
插件来下载图片的示例代码。
首先,确保你的Flutter项目已经创建,并且你已经添加了image_downloader
插件到你的pubspec.yaml
文件中。
1. 添加依赖
在你的pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
image_downloader: ^0.x.x # 请检查最新版本号并替换
然后运行flutter pub get
来安装依赖。
2. 导入插件
在你需要使用图片下载功能的Dart文件中导入image_downloader
插件:
import 'package:image_downloader/image_downloader.dart';
3. 使用插件下载图片
以下是一个完整的示例,展示如何下载并保存图片到设备的存储中:
import 'package:flutter/material.dart';
import 'package:image_downloader/image_downloader.dart';
import 'package:permission_handler/permission_handler.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Image Downloader Example'),
),
body: Center(
child: DownloadImageButton(),
),
),
);
}
}
class DownloadImageButton extends StatefulWidget {
@override
_DownloadImageButtonState createState() => _DownloadImageButtonState();
}
class _DownloadImageButtonState extends State<DownloadImageButton> {
@override
void initState() {
super.initState();
// 请求存储权限(需要Android和iOS权限处理)
_requestPermissions();
}
Future<void> _requestPermissions() async {
// 请求存储权限
var status = await Permission.storage.status;
if (!status.isGranted) {
Map<Permission, PermissionStatus> permissions = await Permission.storage.request();
status = permissions[Permission.storage]!;
}
if (status.isDenied || status.isPermanentlyDenied) {
// 处理权限被拒绝的情况
// 可以提示用户去设置中手动开启权限
}
}
void _downloadImage() async {
var imageUrl =
'https://example.com/path/to/your/image.jpg'; // 替换为你要下载的图片URL
var id = await ImageDownloader.downloadImage(imageUrl,
fileName: 'downloaded_image', saveToGallery: true);
if (id == null) {
// 下载失败
print('Failed to download image');
} else {
// 下载成功
print('Image downloaded successfully with ID: $id');
}
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: _downloadImage,
child: Text('Download Image'),
);
}
}
4. 注意事项
-
权限处理:在Android和iOS上,下载图片到设备存储需要相应的存储权限。上面的示例代码使用了
permission_handler
插件来处理权限请求。你需要将permission_handler
添加到你的pubspec.yaml
中并运行flutter pub get
来安装它。 -
依赖版本:请确保你使用的
image_downloader
和permission_handler
插件的版本是最新的,并且与你的Flutter SDK版本兼容。 -
错误处理:在实际应用中,你应该添加更多的错误处理逻辑,比如处理网络错误、文件写入错误等。
这个示例展示了如何在Flutter应用中下载并保存图片到设备的存储中。希望这对你有帮助!