You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter使用file_manager获取PDF路径及外部存储访问问题求助

PDF阅读器文件列表页面修复方案

关键问题修复点

1. 外部存储访问配置

  • 首先添加权限处理依赖,在pubspec.yaml中加入:
    permission_handler: ^10.2.0
    
  • 将页面改为StatefulWidget,在初始化时申请存储权限,并指定控制器初始路径为外部存储根目录

2. PDF文件筛选逻辑修正

  • 移除原代码中错误的异步循环(await不能在同步builder中使用,且遍历修改原列表会导致异常)
  • 通过where方法过滤列表:保留所有目录,仅保留后缀为.pdf的文件

修正后的完整代码

import 'dart:io';
import 'HomePage.dart';
import 'package:file_manager/controller/file_manager_controller.dart';
import 'package:file_manager/file_manager.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';

class FolderPage extends StatefulWidget {
  const FolderPage({Key? key}) : super(key: key);

  @override
  State<FolderPage> createState() => _FolderPageState();
}

class _FolderPageState extends State<FolderPage> {
  late final FileManagerController controller;

  @override
  void initState() {
    super.initState();
    _initStoragePermissionAndController();
  }

  // 申请存储权限并初始化控制器
  Future<void> _initStoragePermissionAndController() async {
    // 请求存储权限
    final status = await Permission.storage.request();
    if (status.isGranted) {
      // 获取外部存储根目录
      final externalDir = await getExternalStorageDirectory();
      if (externalDir != null) {
        // 初始化控制器,指向外部存储根目录(适配不同设备路径)
        controller = FileManagerController(
          initialDirectory: externalDir.parent.parent,
        );
        setState(() {});
      }
    } else {
      // 权限被拒绝, fallback 到内部存储
      controller = FileManagerController();
    }
  }

  @override
  Widget build(BuildContext context) {
    // 权限未初始化时显示加载状态
    if (!mounted || !controller.isInitialized) {
      return const Scaffold(
        body: Center(child: CircularProgressIndicator()),
      );
    }

    return ControlBackButton(
      controller: controller,
      child: FileManager(
        controller: controller,
        builder: (context, snapshot) {
          List<FileSystemEntity> entities = snapshot;
          
          // 筛选目录和PDF文件
          final filteredEntities = entities.where((entity) {
            if (FileManager.isDirectory(entity)) {
              return true;
            } else if (FileManager.isFile(entity)) {
              return entity.path.toLowerCase().endsWith('.pdf');
            }
            return false;
          }).toList();

          return Container(
            padding: const EdgeInsets.only(top: 3.0),
            decoration: const BoxDecoration(color: Color.fromARGB(255, 35, 51, 75)),
            child: ListView.builder(
              itemCount: filteredEntities.length,
              itemBuilder: (context, index) {
                final entity = filteredEntities[index];
                return Container(
                  margin: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0),
                  decoration: BoxDecoration(
                    borderRadius: const BorderRadius.all(Radius.circular(12.0)),
                    color: const Color.fromRGBO(255, 255, 255, 0.4),
                  ),
                  child: ListTile(
                    leading: CircleAvatar(
                      backgroundColor: const Color.fromARGB(255, 40, 58, 85),
                      child: FileManager.isFile(entity)
                          ? const Icon(Icons.picture_as_pdf, color: Colors.white)
                          : const Icon(Icons.folder, color: Colors.white),
                    ),
                    title: Text(
                      FileManager.basename(entity),
                      style: const TextStyle(color: Colors.white),
                    ),
                    onTap: () {
                      if (FileManager.isDirectory(entity)) {
                        controller.openDirectory(entity);
                      } else {
                        // 在此添加打开PDF文件的逻辑
                      }
                    },
                  ),
                );
              },
            ),
          );
        },
      ),
    );
  }
}

额外说明

  • 外部存储路径适配:externalDir.parent.parent用于适配部分设备中getExternalStorageDirectory()返回的内部存储子目录,确保指向真正的外部存储根
  • 权限处理:若用户拒绝权限,页面自动切换到内部存储,可根据需求添加权限引导弹窗
  • 视觉优化:将原文件图标替换为PDF专属图标,提升用户识别度

内容的提问来源于stack exchange,提问作者Ahsan Tony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 09:15:35