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

如何通过react-native-fs/react-native-blob获取安卓设备所有PDF文件并展示?

安卓设备获取所有PDF文件名称和路径的解决方案

1. 权限配置(核心前提)

首先在AndroidManifest.xml中添加对应安卓版本的存储权限:

  • 安卓12及以下版本:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
  ...
  android:requestLegacyExternalStorage="true"> <!-- 适配安卓10分区存储规则 -->
  • 安卓13及以上版本:
<uses-permission android:name="android.permission.READ_MEDIA_DOCUMENTS" />

若需访问所有文件(含其他应用私有目录),需添加特殊权限(仅适用于合规场景,需用户手动在设置开启):

<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />

2. 用react-native-fs实现递归扫描

先确保依赖安装完成:

npm install react-native-fs --save
# RN0.59及以下版本需执行link
react-native link react-native-fs

编写扫描逻辑:

import RNFS from 'react-native-fs';

// 存储扫描到的PDF文件
let pdfFiles = [];

// 递归扫描目录
const scanDirectory = async (dirPath) => {
  try {
    const files = await RNFS.readDir(dirPath);
    for (const file of files) {
      if (file.isDirectory()) {
        // 递归扫描子目录
        await scanDirectory(file.path);
      } else {
        // 筛选PDF文件(不区分大小写)
        if (file.name.toLowerCase().endsWith('.pdf')) {
          pdfFiles.push({
            name: file.name,
            path: file.path
          });
        }
      }
    }
  } catch (err) {
    console.error('扫描目录出错:', err);
  }
};

// 启动扫描流程
const startScanning = async () => {
  pdfFiles = [];
  // 安卓外部存储根目录
  const externalRoot = RNFS.ExternalStorageDirectoryPath;
  // 优先扫描常用公共目录(减少不必要的扫描耗时)
  const targetDirs = [
    `${externalRoot}/Download`,
    `${externalRoot}/Documents`,
    `${externalRoot}/Books`
  ];

  for (const dir of targetDirs) {
    // 先校验目录是否存在
    const isExist = await RNFS.exists(dir);
    if (isExist) {
      await scanDirectory(dir);
    }
  }

  // 扫描完成后更新状态,用于页面渲染
  // setPdfList(pdfFiles); // 需在组件中定义对应state
  console.log('扫描到的PDF文件:', pdfFiles);
};

3. 运行时权限请求

必须先获取用户授权才能访问存储,可直接用React Native内置API处理:

import { PermissionsAndroid } from 'react-native';

const requestStoragePermission = async () => {
  try {
    const granted = await PermissionsAndroid.request(
      // 安卓13+替换为PermissionsAndroid.PERMISSIONS.READ_MEDIA_DOCUMENTS
      PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
      {
        title: "存储权限申请",
        message: "需要访问您的存储以查找PDF文件",
        buttonPositive: "确定",
        buttonNegative: "取消"
      }
    );
    if (granted === PermissionsAndroid.RESULTS.GRANTED) {
      // 权限通过,启动扫描
      await startScanning();
    } else {
      console.log("存储权限被拒绝");
    }
  } catch (err) {
    console.warn(err);
  }
};

4. 页面渲染扫描结果

在组件中调用权限请求,并将扫描到的PDF列表渲染到屏幕:

import { useState, useEffect } from 'react';
import { View, Text, FlatList, StyleSheet } from 'react-native';

export default function PDFScannerPage() {
  const [pdfList, setPdfList] = useState([]);

  useEffect(() => {
    // 重写startScanning中的结果处理,将数据同步到state
    const customStartScanning = async () => {
      pdfFiles = [];
      const externalRoot = RNFS.ExternalStorageDirectoryPath;
      const targetDirs = [
        `${externalRoot}/Download`,
        `${externalRoot}/Documents`
      ];
      for (const dir of targetDirs) {
        const isExist = await RNFS.exists(dir);
        if (isExist) await scanDirectory(dir);
      }
      setPdfList(pdfFiles);
    };

    // 包装权限请求与扫描逻辑
    const initScan = async () => {
      await requestStoragePermission();
    };
    initScan();
  }, []);

  return (
    <View style={styles.container}>
      <Text style={styles.title}>扫描到的PDF文件</Text>
      <FlatList
        data={pdfList}
        keyExtractor={(item) => item.path}
        renderItem={({ item }) => (
          <View style={styles.itemCard}>
            <Text style={styles.fileName}>{item.name}</Text>
            <Text style={styles.filePath}>{item.path}</Text>
          </View>
        )}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 16,
    backgroundColor: '#fff'
  },
  title: {
    fontSize: 20,
    fontWeight: '600',
    marginBottom: 16
  },
  itemCard: {
    padding: 12,
    borderBottomWidth: 1,
    borderBottomColor: '#eee',
    marginBottom: 8
  },
  fileName: {
    fontSize: 16,
    fontWeight: '500'
  },
  filePath: {
    fontSize: 12,
    color: '#666',
    marginTop: 4
  }
});

常见问题排查

  • 无法获取全部PDF:安卓10+的分区存储限制,无法访问其他应用的私有目录(如Android/data下其他应用的文件夹),这是系统级限制;若需访问所有文件,必须引导用户开启MANAGE_EXTERNAL_STORAGE权限。
  • 扫描速度慢:可跳过系统隐藏目录、临时文件目录,或仅扫描常用的几个公共目录(如Download、Documents)。
  • 权限失效:确保在运行时主动请求权限,而非仅在Manifest中声明。

内容的提问来源于stack exchange,提问作者Anujfresco Fresco

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 07:05:33