Flutter文件管理插件file_manager的使用

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

Flutter文件管理插件file_manager的使用

简介

file_manager 是一个功能强大的Flutter插件,它允许你管理文件和文件夹、选择文件和文件夹,并且可以执行许多其他操作。该插件设计得就像Flutter框架的一部分一样自然。

FileManager-Banner

GitHub License | Code Size | Top Language | Language Count | Latest Tag | Issues

兼容性

  • ✅ Android
  • ✅ Linux
  • ❌ Windows (正在进行中)
  • ❌ MacOS (有活跃问题)

使用方法

安装

pubspec.yaml 文件中添加以下依赖:

dependencies:
  file_manager: ^1.0.0

给应用程序存储权限

Android

android/app/src/main/AndroidManifest.xml 中添加以下权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.xxx.yyy">
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
    
    <application
      android:requestLegacyExternalStorage="true"   
      .../>
</manifest>

你需要运行时请求权限,可以通过 permission_handler 包来实现,或者直接使用 FileManager 请求权限:

await controller.requestFilesAccessPermission();
or 
await FileManager.requestFilesAccessPermission();

基本设置

创建 FileManagerController 实例:

final FileManagerController controller = FileManagerController();

示例代码

以下是一个完整的示例代码,展示了如何使用 file_manager 插件:

import 'dart:io';
import 'package:file_manager/file_manager.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      themeMode: ThemeMode.dark,
      theme: ThemeData(useMaterial3: true),
      darkTheme: ThemeData(useMaterial3: true, brightness: Brightness.dark),
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  final FileManagerController controller = FileManagerController();

  @override
  Widget build(BuildContext context) {
    return ControlBackButton(
      controller: controller,
      child: Scaffold(
        appBar: appBar(context),
        body: FileManager(
          controller: controller,
          builder: (context, snapshot) {
            final List<FileSystemEntity> entities = snapshot;
            return ListView.builder(
              padding: EdgeInsets.symmetric(horizontal: 2, vertical: 0),
              itemCount: entities.length,
              itemBuilder: (context, index) {
                FileSystemEntity entity = entities[index];
                return Card(
                  child: ListTile(
                    leading: FileManager.isFile(entity)
                        ? Icon(Icons.feed_outlined)
                        : Icon(Icons.folder),
                    title: Text(FileManager.basename(
                      entity,
                      showFileExtension: true,
                    )),
                    subtitle: subtitle(entity),
                    onTap: () async {
                      if (FileManager.isDirectory(entity)) {
                        // 打开文件夹
                        controller.openDirectory(entity);
                      } else {
                        // 执行文件相关任务
                      }
                    },
                  ),
                );
              },
            );
          },
        ),
        floatingActionButton: FloatingActionButton.extended(
          onPressed: () async {
            FileManager.requestFilesAccessPermission();
          },
          label: Text("Request File Access Permission"),
        ),
      ),
    );
  }

  AppBar appBar(BuildContext context) {
    return AppBar(
      actions: [
        IconButton(
          onPressed: () => createFolder(context),
          icon: Icon(Icons.create_new_folder_outlined),
        ),
        IconButton(
          onPressed: () => sort(context),
          icon: Icon(Icons.sort_rounded),
        ),
        IconButton(
          onPressed: () => selectStorage(context),
          icon: Icon(Icons.sd_storage_rounded),
        )
      ],
      title: ValueListenableBuilder<String>(
        valueListenable: controller.titleNotifier,
        builder: (context, title, _) => Text(title),
      ),
      leading: IconButton(
        icon: Icon(Icons.arrow_back),
        onPressed: () async {
          await controller.goToParentDirectory();
        },
      ),
    );
  }

  Widget subtitle(FileSystemEntity entity) {
    return FutureBuilder<FileStat>(
      future: entity.stat(),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          if (entity is File) {
            int size = snapshot.data!.size;

            return Text(
              "${FileManager.formatBytes(size)}",
            );
          }
          return Text(
            "${snapshot.data!.modified}".substring(0, 10),
          );
        } else {
          return Text("");
        }
      },
    );
  }

  Future<void> selectStorage(BuildContext context) async {
    return showDialog(
      context: context,
      builder: (context) => Dialog(
        child: FutureBuilder<List<Directory>>(
          future: FileManager.getStorageList(),
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              final List<FileSystemEntity> storageList = snapshot.data!;
              return Padding(
                padding: const EdgeInsets.all(10.0),
                child: Column(
                    mainAxisSize: MainAxisSize.min,
                    children: storageList
                        .map((e) => ListTile(
                              title: Text(
                                "${FileManager.basename(e)}",
                              ),
                              onTap: () {
                                controller.openDirectory(e);
                                Navigator.pop(context);
                              },
                            ))
                        .toList()),
              );
            }
            return Dialog(
              child: CircularProgressIndicator(),
            );
          },
        ),
      ),
    );
  }

  sort(BuildContext context) async {
    showDialog(
      context: context,
      builder: (context) => Dialog(
        child: Container(
          padding: EdgeInsets.all(10),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              ListTile(
                  title: Text("Name"),
                  onTap: () {
                    controller.sortBy(SortBy.name);
                    Navigator.pop(context);
                  }),
              ListTile(
                  title: Text("Size"),
                  onTap: () {
                    controller.sortBy(SortBy.size);
                    Navigator.pop(context);
                  }),
              ListTile(
                  title: Text("Date"),
                  onTap: () {
                    controller.sortBy(SortBy.date);
                    Navigator.pop(context);
                  }),
              ListTile(
                  title: Text("Type"),
                  onTap: () {
                    controller.sortBy(SortBy.type);
                    Navigator.pop(context);
                  }),
            ],
          ),
        ),
      ),
    );
  }

  createFolder(BuildContext context) async {
    showDialog(
      context: context,
      builder: (context) {
        TextEditingController folderName = TextEditingController();
        return Dialog(
          child: Container(
            padding: EdgeInsets.all(10),
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                ListTile(
                  title: TextField(
                    controller: folderName,
                  ),
                ),
                ElevatedButton(
                  onPressed: () async {
                    try {
                      // 创建文件夹
                      await FileManager.createFolder(
                          controller.getCurrentPath, folderName.text);
                      // 打开创建的文件夹
                      controller.setCurrentPath =
                          controller.getCurrentPath + "/" + folderName.text;
                    } catch (e) {}

                    Navigator.pop(context);
                  },
                  child: Text('Create Folder'),
                )
              ],
            ),
          ),
        );
      },
    );
  }
}

其他功能

  • ControlBackButton: 当当前目录不是根目录时,此小部件注册回调以防止用户关闭窗口或控制系统的返回按钮。
  • isFileisDirectory: 检查 FileSystemEntity 是否为文件或目录。
  • basename: 获取目录或文件的基本名称。
  • formatBytes: 将字节转换为人类可读的大小。
  • getFileExtension: 返回文件扩展名。
  • getStorageList: 获取设备上的可用存储列表。
  • createFolder: 创建目录(如果不存在)。

显示支持和贡献

如果你觉得这个插件对你有帮助,请给它一个星标!

GitHub stars GitHub forks GitHub followers

项目由 DevsOnFlutter 创建并维护。

欢迎贡献!如果你有任何改进的想法,请提交Pull Request。


更多关于Flutter文件管理插件file_manager的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter文件管理插件file_manager的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,关于在Flutter中使用file_manager插件进行文件管理,下面是一个简单的代码案例来展示其基本用法。需要注意的是,file_manager并不是一个广泛认知的标准Flutter插件,因此我假设你可能是指一个具有类似功能的第三方插件,或者是一个自定义的插件。不过,Flutter生态系统中常用的文件管理插件是path_providerfile_picker。由于file_manager不是标准插件,我将基于path_providerfile_picker展示文件管理的基本操作,因为它们是广泛使用的替代方案。

使用path_providerfile_picker进行文件管理

1. 添加依赖

首先,在你的pubspec.yaml文件中添加必要的依赖:

dependencies:
  flutter:
    sdk: flutter
  path_provider: ^2.0.9  # 请检查最新版本
  file_picker: ^4.3.3  # 请检查最新版本

然后运行flutter pub get来安装这些依赖。

2. 获取应用文档目录

使用path_provider来获取应用的文档目录路径:

import 'package:flutter/material.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('File Management'),
        ),
        body: Center(
          child: FutureBuilder<String>(
            future: _getApplicationDocumentsDirectory(),
            builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                if (snapshot.hasError) {
                  return Text('Error: ${snapshot.error}');
                } else {
                  return Text('Application documents directory: ${snapshot.data}');
                }
              } else {
                return CircularProgressIndicator();
              }
            },
          ),
        ),
      ),
    );
  }

  Future<String> _getApplicationDocumentsDirectory() async {
    final directory = await getApplicationDocumentsDirectory();
    return directory.path;
  }
}

3. 使用file_picker选择文件

接下来,使用file_picker来让用户选择文件:

import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.dart';

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('File Management'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              ElevatedButton(
                onPressed: () async {
                  FilePickerResult? result = await FilePicker.platform.pickFiles(
                    type: FileType.any,
                  );

                  if (result != null) {
                    FilePickerFile? file = result.files.first;
                    print('Selected file path: ${file.path}');
                    // 在这里你可以进一步处理文件,比如读取内容或保存到其他位置
                  }
                },
                child: Text('Select File'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

注意

  • 上述代码展示了如何使用path_provider获取应用的文档目录路径,并使用file_picker让用户选择文件。
  • 在实际应用中,你可能需要根据所选文件的类型(图片、视频、文档等)进行不同的处理。
  • 如果确实有一个名为file_manager的插件,并且它提供了特定的功能,你应该参考该插件的官方文档来获取准确的使用方法和示例代码。

希望这个示例能帮助你理解如何在Flutter中进行文件管理。如果有任何进一步的问题,请随时提问!

回到顶部