forked from akai/readest
121 lines
3.0 KiB
TypeScript
121 lines
3.0 KiB
TypeScript
import { getAPIBaseUrl, isWebAppPlatform } from '@/services/environment';
|
|
import { getUserID } from '@/utils/access';
|
|
import { fetchWithAuth } from '@/utils/fetch';
|
|
import {
|
|
tauriUpload,
|
|
tauriDownload,
|
|
webUpload,
|
|
webDownload,
|
|
ProgressHandler,
|
|
ProgressPayload,
|
|
} from '@/utils/transfer';
|
|
|
|
const API_ENDPOINTS = {
|
|
upload: getAPIBaseUrl() + '/storage/upload',
|
|
download: getAPIBaseUrl() + '/storage/download',
|
|
delete: getAPIBaseUrl() + '/storage/delete',
|
|
};
|
|
|
|
export const createProgressHandler = (
|
|
totalFiles: number,
|
|
completedFilesRef: { count: number },
|
|
onProgress?: ProgressHandler,
|
|
) => {
|
|
return (progress: ProgressPayload) => {
|
|
const fileProgress = progress.progress / progress.total;
|
|
const overallProgress = ((completedFilesRef.count + fileProgress) / totalFiles) * 100;
|
|
|
|
if (onProgress) {
|
|
onProgress({
|
|
progress: overallProgress,
|
|
total: 100,
|
|
transferSpeed: progress.transferSpeed,
|
|
});
|
|
}
|
|
};
|
|
};
|
|
|
|
export const uploadFile = async (
|
|
file: File,
|
|
fileFullPath: string,
|
|
onProgress?: ProgressHandler,
|
|
bookHash?: string,
|
|
) => {
|
|
try {
|
|
const response = await fetchWithAuth(API_ENDPOINTS.upload, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
fileName: file.name,
|
|
fileSize: file.size,
|
|
bookHash,
|
|
}),
|
|
});
|
|
|
|
const { uploadUrl } = await response.json();
|
|
if (isWebAppPlatform()) {
|
|
await webUpload(file, uploadUrl, onProgress);
|
|
} else {
|
|
await tauriUpload(uploadUrl, fileFullPath, 'PUT', onProgress);
|
|
}
|
|
} catch (error) {
|
|
console.error('File upload failed:', error);
|
|
if (error instanceof Error) {
|
|
throw error;
|
|
}
|
|
throw new Error('File upload failed');
|
|
}
|
|
};
|
|
|
|
export const downloadFile = async (
|
|
filePath: string,
|
|
fileFullPath: string,
|
|
onProgress?: ProgressHandler,
|
|
) => {
|
|
try {
|
|
const userId = await getUserID();
|
|
if (!userId) {
|
|
throw new Error('Not authenticated');
|
|
}
|
|
|
|
const fileKey = `${userId}/${filePath}`;
|
|
const response = await fetchWithAuth(
|
|
`${API_ENDPOINTS.download}?fileKey=${encodeURIComponent(fileKey)}`,
|
|
{
|
|
method: 'GET',
|
|
},
|
|
);
|
|
|
|
const { downloadUrl } = await response.json();
|
|
|
|
if (isWebAppPlatform()) {
|
|
return await webDownload(downloadUrl, onProgress);
|
|
} else {
|
|
await tauriDownload(downloadUrl, fileFullPath, onProgress);
|
|
return;
|
|
}
|
|
} catch (error) {
|
|
console.error(`File '${filePath}' download failed:`, error);
|
|
throw new Error('File download failed');
|
|
}
|
|
};
|
|
|
|
export const deleteFile = async (filePath: string) => {
|
|
try {
|
|
const userId = await getUserID();
|
|
if (!userId) {
|
|
throw new Error('Not authenticated');
|
|
}
|
|
|
|
const fileKey = `${userId}/${filePath}`;
|
|
await fetchWithAuth(`${API_ENDPOINTS.delete}?fileKey=${encodeURIComponent(fileKey)}`, {
|
|
method: 'DELETE',
|
|
});
|
|
} catch (error) {
|
|
console.error('File deletion failed:', error);
|
|
throw new Error('File deletion failed');
|
|
}
|
|
};
|