import { useCallback, useState } from 'react' import * as FileSystem from 'expo-file-system' import * as MediaLibrary from 'expo-media-library' export type MediaType = 'image' | 'video' export interface DownloadResult { success: boolean error?: string } export const useDownloadMedia = () => { const [loading, setLoading] = useState(false) const [error, setError] = useState(null) const [progress, setProgress] = useState(0) const download = useCallback(async (url: string, type: MediaType): Promise => { setLoading(true) setError(null) setProgress(0) let fileUri: string | null = null try { // 1. 请求媒体库权限 const { status } = await MediaLibrary.requestPermissionsAsync() if (status !== 'granted') { setError('Permission denied') setLoading(false) return { success: false, error: 'Permission denied' } } // 2. 生成临时文件名 const extension = type === 'video' ? 'mp4' : 'jpg' const fileName = `download_${Date.now()}.${extension}` fileUri = FileSystem.documentDirectory + fileName // 3. 下载文件(带进度) const downloadResumable = FileSystem.createDownloadResumable( url, fileUri, {}, (downloadProgress) => { const progressValue = downloadProgress.totalBytesWritten / downloadProgress.totalBytesExpectedToWrite setProgress(progressValue) } ) const downloadResult = await downloadResumable.downloadAsync() if (!downloadResult?.uri) { throw new Error('Download failed') } // 4. 保存到相册 await MediaLibrary.saveToLibraryAsync(downloadResult.uri) // 5. 清理临时文件 await FileSystem.deleteAsync(fileUri, { idempotent: true }) setLoading(false) setProgress(0) return { success: true } } catch (e) { const errorMessage = e instanceof Error ? e.message : 'Download failed' setError(errorMessage) setLoading(false) setProgress(0) // 尝试清理临时文件 if (fileUri) { try { await FileSystem.deleteAsync(fileUri, { idempotent: true }) } catch { // 忽略清理错误 } } return { success: false, error: errorMessage } } }, []) return { download, loading, error, progress } }