如何在React Native中实现带启停续传及后台运行的文件下载功能?
React Native 实现完整文件下载功能(支持启停、续传、后台运行)
针对你遇到的第三方库局限性问题,推荐使用react-native-blob-util(这是维护活跃的rn-fetch-blob替代项目),结合原生权限配置,可以实现全平台的完整下载能力。以下是具体实现步骤:
1. 安装依赖
npm install react-native-blob-util # 或使用yarn yarn add react-native-blob-util
iOS需执行pod安装:
cd ios && pod install && cd ..
2. 配置后台运行权限
iOS端
在项目的Info.plist中添加后台模式配置:
<key>UIBackgroundModes</key> <array> <string>fetch</string> <string>remote-notification</string> </array>
也可以通过Xcode可视化配置:项目设置 → Signing & Capabilities → 添加Background Modes,勾选"Background fetch"和"Remote notifications"。
Android端
在AndroidManifest.xml中添加必要权限与服务声明:
<!-- 基础权限 --> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 后台服务权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <!-- 在application标签内添加服务 --> <service android:name="com.RNBlobUtil.RNBlobUtilDownloadService" android:foregroundServiceType="dataSync"/>
3. 核心功能代码实现
以下是包含启动、续传、停止、进度监听的完整组件:
import React, { useState, useRef } from 'react'; import { View, Button, Text, StyleSheet } from 'react-native'; import RNBlobUtil from 'react-native-blob-util'; const DownloadComponent = () => { const [progress, setProgress] = useState(0); const [isDownloading, setIsDownloading] = useState(false); const downloadTask = useRef(null); const targetFilePath = `${RNBlobUtil.fs.dirs.DocumentDir}/target-file.zip`; const downloadUrl = 'https://example.com/your-large-file.zip'; // 启动/续传下载 const handleStartDownload = async () => { setIsDownloading(true); let requestHeaders = {}; let existingFileSize = 0; // 检查文件是否已存在,准备续传 const fileExists = await RNBlobUtil.fs.exists(targetFilePath); if (fileExists) { const fileStats = await RNBlobUtil.fs.stat(targetFilePath); existingFileSize = fileStats.size; requestHeaders['Range'] = `bytes=${existingFileSize}-`; } // 创建下载任务 downloadTask.current = RNBlobUtil.config({ path: targetFilePath, append: fileExists, // 开启续传模式 android: { // Android前台通知,防止后台被杀死 notification: true, notificationTitle: '文件下载', notificationDescription: '正在下载,请稍候', notificationColor: '#4CAF50', }, }) .fetch('GET', downloadUrl, requestHeaders) .progress((receivedBytes, totalBytes) => { // 计算真实进度(含已下载部分) const totalSize = existingFileSize + totalBytes; const currentReceived = existingFileSize + receivedBytes; setProgress(Math.round((currentReceived / totalSize) * 100)); }) .then(() => { console.log('下载完成'); setProgress(100); setIsDownloading(false); }) .catch(err => { console.error('下载中断/失败:', err.message); setIsDownloading(false); }); }; // 停止下载 const handleStopDownload = () => { if (downloadTask.current) { downloadTask.current.cancel(); downloadTask.current = null; setIsDownloading(false); } }; return ( <View style={styles.container}> <Text style={styles.progressText}>下载进度: {progress}%</Text> <Button title={isDownloading ? '停止下载' : '启动/续传'} onPress={isDownloading ? handleStopDownload : handleStartDownload} color={isDownloading ? '#f44336' : '#2196F3'} /> </View> ); }; const styles = StyleSheet.create({ container: { padding: 20, alignItems: 'center', justifyContent: 'center', flex: 1, }, progressText: { fontSize: 18, marginBottom: 20, }, }); export default DownloadComponent;
关键细节说明
- 续传支持:通过检查本地文件大小,给请求添加
Range头实现,前提是服务器支持Partial Content(返回206状态码)。 - 停止下载:通过保存下载任务引用,调用
cancel()方法终止任务,确保资源释放。 - 后台运行:iOS依赖系统后台下载机制,Android通过前台服务维持进程,避免被系统回收。
- 兼容性:react-native-blob-util支持RN 0.60+版本,维护状态活跃,解决了旧库的版本兼容问题。
内容的提问来源于stack exchange,提问作者Digamber negi
相关产品推荐
相关产品推荐

