72 lines
1.9 KiB
TypeScript
72 lines
1.9 KiB
TypeScript
import { useCallback, useState } from 'react'
|
|
import * as MediaLibrary from 'expo-media-library'
|
|
|
|
export type MediaType = 'image' | 'video'
|
|
|
|
export interface DownloadResult {
|
|
success: boolean
|
|
error?: string
|
|
}
|
|
|
|
// 使用 fetch 下载文件并转换为 base64
|
|
const downloadToCache = async (url: string, fileName: string): Promise<string> => {
|
|
const response = await fetch(url)
|
|
if (!response.ok) {
|
|
throw new Error('Download failed')
|
|
}
|
|
|
|
const blob = await response.blob()
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const reader = new FileReader()
|
|
reader.onloadend = () => {
|
|
const base64data = reader.result as string
|
|
resolve(base64data)
|
|
}
|
|
reader.onerror = reject
|
|
reader.readAsDataURL(blob)
|
|
})
|
|
}
|
|
|
|
export const useDownloadMedia = () => {
|
|
const [loading, setLoading] = useState(false)
|
|
const [error, setError] = useState<string | null>(null)
|
|
const [progress, setProgress] = useState(0)
|
|
|
|
const download = useCallback(async (url: string, type: MediaType): Promise<DownloadResult> => {
|
|
setLoading(true)
|
|
setError(null)
|
|
setProgress(0)
|
|
|
|
try {
|
|
// 1. 请求媒体库权限
|
|
const { status } = await MediaLibrary.requestPermissionsAsync()
|
|
if (status !== 'granted') {
|
|
setError('Permission denied')
|
|
setLoading(false)
|
|
return { success: false, error: 'Permission denied' }
|
|
}
|
|
|
|
setProgress(0.3)
|
|
|
|
// 2. 使用 MediaLibrary.saveToLibraryAsync 直接从 URL 保存
|
|
// 这个方法可以直接接受远程 URL
|
|
await MediaLibrary.saveToLibraryAsync(url)
|
|
|
|
setProgress(1)
|
|
setLoading(false)
|
|
setProgress(0)
|
|
return { success: true }
|
|
} catch (e) {
|
|
const errorMessage = e instanceof Error ? e.message : 'Download failed'
|
|
setError(errorMessage)
|
|
setLoading(false)
|
|
setProgress(0)
|
|
|
|
return { success: false, error: errorMessage }
|
|
}
|
|
}, [])
|
|
|
|
return { download, loading, error, progress }
|
|
}
|