react-native-blob-util下载文件展示进度,随时取消(原创仅供参考)这段代码通过封装一个下载文件的功能
这段代码通过封装一个下载文件的功能,利用 React 状态管理和异步处理,能够在 React Native 应用中轻松实现文件下载、进度跟踪和取消下载的功能。每个步骤都以清晰的方式处理下载任务,使得代码易于理解和维护。
下载功能实现
1. 引入必要库和 hooks
useRef
:React Hook,用于创建一个引用对象,能够在组件之间保留状态。CommonBridge
和ReactNativeBlobUtil
:这两个库用于处理文件下载和本地文件操作。
2. 定义状态和引用
const downloadTaskRef = useRef({})
downloadTaskRef
被用作引用以存储下载任务的实例,这样可以在多个函数中共享这个状态。
3. 定义下载文件的函数
const downloadFile = async (url: string) => {
downloadFile
是一个异步函数,接收一个 URL 作为参数,用于下载文件。
4. 构建文件路径
const fileName = 'xxx.pdf'
const filePath = `${...}`
-
fileName
定义了下载文件的名称。 -
filePath
动态确定文件存储路径:- 如果是在 Android 设备上,使用
/storage/emulated/0/Download
目录。 - 如果是在 iOS 设备上,使用
ReactNativeBlobUtil.fs.dirs.CacheDir
。
- 如果是在 Android 设备上,使用
5. 配置下载任务
const { config } = ReactNativeBlobUtil
downloadTaskRef.current = config({
path: filePath,
fileCache: true
})
.fetch('GET', url, {})
- 使用
ReactNativeBlobUtil
的config
方法配置下载任务,指定文件存储路径以及启用文件缓存。 - 接着用
fetch
方法开始下载,HTTP 请求使用 'GET' 方法。
6. 下载进度更新
.progress((percent, total) => {
setProgress(percent / total)
})
- 监听下载进度,
percent
和total
是当前下载的字节数和文件总字节数,通过setProgress
更新进度状态。
7. 处理下载完成和错误
try {
const response = await downloadTaskRef.current
setProgress(0)
...
} catch (error: any) {
setProgress(-1)
...
}
-
使用
try...catch
结构捕获异步过程中的错误。如果下载成功,重置进度状态并根据操作系统执行相应操作:- 对于 Android,使用
ReactNativeBlobUtil.android.addCompleteDownload
提示用户下载完成,并显示通知。 - 对于 iOS,使用
ReactNativeBlobUtil.ios.previewDocument
预览下载的文档。
- 对于 Android,使用
8. 取消下载的方法
const cancelDownload = useCallback(() => {
if (downloadTaskRef.current) {
downloadTaskRef.current.cancel((error: any) => {
setProgress(-1)
})
downloadTaskRef.current = null
}
}, [])
-
cancelDownload
是一个回调函数,用于取消下载任务:- 首先检查是否有下载任务在进行,如果有,则调用
cancel
方法取消下载,并设置进度状态为 -1 表示下载被取消。 - 最后,重置
downloadTaskRef.current
为null
。
- 首先检查是否有下载任务在进行,如果有,则调用
进度条
这段代码实现了一个简单的进度条,其中进度是动态变化的,用于表示某种任务的完成情况。你可以通过修改 progress
变量的值,来实现进度条的动态更新。
<Progress.Bar
progress={progress}
/>
-
import * as Progress from 'react-native-progress'
:- 这部分表示开始使用
Progress.Bar
组件
- 这部分表示开始使用
-
progress={progress}
:- 这里的
progress
是一个变量,代表进度条的进度值,通常在 0 到 1 之间。例如,0 表示没有进度,1 表示进度完成。在实际使用中,你可能会用一个状态值来动态更新这个变量。
- 这里的
关键代码
const [progress, setProgress] = useState(-1)
const downloadTaskRef = useRef({})
const downloadFile = async (url: string) => {
const fileName = 'xxxx.pdf'
const filePath = `${
CommonBridge.isAndroid()
? '/storage/emulated/0/Download'
: ReactNativeBlobUtil.fs.dirs.CacheDir
}/${fileName}`
const { config } = ReactNativeBlobUtil
downloadTaskRef.current = config({
path: filePath,
fileCache: true
})
.fetch('GET', url, {})
.progress((percent, total) => {
setProgress(percent / total)
})
try {
const response = await downloadTaskRef.current
setProgress(0)
if (CommonBridge.isAndroid()) {
ReactNativeBlobUtil.android
.addCompleteDownload({
title: fileName,
description: '下载完成',
mime: 'application/pdf',
path: response.path(),
showNotification: true
})
.then(() => {
setProgress(1)
showToast('下载完成,请前往 /Download 查看')
})
} else {
setProgress(1)
ReactNativeBlobUtil.ios.previewDocument(response.path())
}
} catch (error: any) {
setProgress(-1)
console.error(
'Error',
error.message.includes('cancelled')
? 'Download was canceled'
: `Download failed: ${error.message}`
)
}
}
const cancelDownload = useCallback(() => {
if (downloadTaskRef.current) {
downloadTaskRef.current.cancel((error: any) => {
setProgress(-1)
})
downloadTaskRef.current = null
}
}, [])
const handleDownload = useCallback(() => {
if (path) {
downloadFile(encodeURI(decodeURIComponent(path)))
}
}, [path])
return progress != 1 && progress != -1 ? (
<View style={styles.progressContainer}>
<Text style={styles.progressText}>{parseInt((progress * 100).toString())}%</Text>
<Progress.Bar
color="rgba(255,255,255,0.9)"
borderWidth={0}
progress={progress}
style={{ height: 4 }}
width={pageWidth - 133}
unfilledColor="rgba(255,255,255,0.1)"
/>
<TouchableOpacity onPress={cancelDownload} style={styles.cancelButton}>
取消
</TouchableOpacity>
</View>
) : (
<TouchableOpacity onPress={handleDownload} style={styles.itemBox}>
下载
</TouchableOpacity>
)
转载自:https://juejin.cn/post/7418133431677894675