Flutter图片下载插件image_downloader的使用

发布于 1周前 作者 caililin 来自 Flutter

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

1 回复

更多关于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_downloaderpermission_handler插件的版本是最新的,并且与你的Flutter SDK版本兼容。

  • 错误处理:在实际应用中,你应该添加更多的错误处理逻辑,比如处理网络错误、文件写入错误等。

这个示例展示了如何在Flutter应用中下载并保存图片到设备的存储中。希望这对你有帮助!

回到顶部