[Android 14 / 新架构] PDF下载在缓存目录的临时文件上因ENOENT错误而崩溃

移动开发 2026-07-09

环境

包名 版本
react-native-pdf 7.0.4
react-native-blob-util 0.23.2
react-native 0.82.1
Android 14 (API 34)
新架构 enabled (newArchEnabled=true)
minSdkVersion 34

错误描述

在使用以下方式加载远程PDF时:

<Pdf
  source={{
    uri: 'https://example.com/doc.pdf',
    cache: true,
  }}
/>

在启用新架构时,应用在Android 14上崩溃。

该失败表现为未处理的Promise拒绝,并绕过绑定在 this.lastRNBFTask 上的 .catch() 处理程序。

该错误也从未传递给 onError 属性。


控制台错误

Uncaught (in promise, id: 0):
Error: /data/user/0/<package>/cache/<sha1>.pdf.tmp:
open failed: ENOENT (No such file or directory)

复现步骤

  1. 启用新架构:
newArchEnabled=true
  1. 目标Android 14(API 34
  2. 渲染:
<Pdf
  source={{
    uri: 'https://example.com/doc.pdf',
    cache: true,
  }}
/>
  1. 在以下情形打开屏幕:

  2. 全新安装,或

  3. 清除Android设置中的应用缓存后

预期行为

  • PDF能成功加载
  • 如果加载失败,错误应通过 onError 属性传递。

实际行为

CacheDir 中的 .pdf.tmp 文件上发生未处理的Promise拒绝,内容为 ENOENT

该错误绕过了库的错误处理,表现为全局未处理拒绝。

onError 从未被调用。


额外背景信息

  • CacheDir 能正确解析
  • 生成的临时文件路径看起来有效。
  • 在执行打开/读取操作时,该文件不存在。
  • 在启用新架构的Android 14上,该问题可稳定复现。
  • 在Android 13及以下版本上不复现。
  • 禁用新架构时不复现。

可能的根本原因

这似乎是在启用新架构的Android 14上缓存/临时文件流程中的一个竞态条件。

位于 CacheDir 内的 .pdf.tmp 文件在实际存在之前就被访问(或在重新创建/清理过程中),导致 react-native-blob-util 抛出 ENOENT

该拒绝在 react-native-pdf 将其转发给 onError 之前就已从Promise链中传播出去。


相关问题

  • react-native-blob-util Android 14 ENOENT 问题
  • RN 0.76+上的TurboModules / 新架构文件系统时序问题

解决方案

在Android 14上启用新架构时,这似乎是 react-native-pdf + react-native-blob-util 中的一个竞态条件。缓存目录本身似乎不是问题所在。.pdf.tmp文件在完全写入或生成完成之前就被打开了,尽管临时路径是可接受的。因此该拒绝在react-native-pdf将其传递给onError之前就已逃逸,Android会抛出ENOENT。

因此,在Android 14的新架构下,最好避免直接对远程PDF使用 cache: true

你也可以改用以下做法:

source={{uri: localFilePath, cache: false}}

简要做法是:先手动将PDF下载到一个稳定的本地文件路径,然后把本地file:// 路径传递给react-native-pdf,并禁用缓存;再检查文件是否存在。这样就能对下载故障、重试和回退界面有完整控制,同时也避免内部临时文件时序问题。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章