fischerX/apps/web/src/lib/file-api.ts

91 lines
3.4 KiB
TypeScript

import api from './api';
import type { File, FileUploadOptions, FileListParams, ProcessImageOptions } from '@fischerx/types';
export const fileApi = {
uploadFile: async (file: File | Blob, options?: FileUploadOptions): Promise<{ success: boolean; data: File }> => {
const formData = new FormData();
formData.append('file', file);
if (options?.category) formData.append('category', options.category);
if (options?.tags) formData.append('tags', JSON.stringify(options.tags));
if (options?.description) formData.append('description', options.description);
const response = await api.post('/files/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
return response.data;
},
uploadMultipleFiles: async (
files: (File | Blob)[],
options?: FileUploadOptions
): Promise<{ success: boolean; data: File[]; errors: Array<{ index: number; error: string }> }> => {
const formData = new FormData();
files.forEach((file) => formData.append('files', file));
if (options?.category) formData.append('category', options.category);
if (options?.tags) formData.append('tags', JSON.stringify(options.tags));
if (options?.description) formData.append('description', options.description);
const response = await api.post('/files/upload/multi', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
return response.data;
},
listFiles: async (params?: FileListParams): Promise<{ success: boolean; data: File[]; meta: { page: number; limit: number; total: number } }> => {
const response = await api.get('/files', { params });
return response.data;
},
getFile: async (id: string): Promise<{ success: boolean; data: File }> => {
const response = await api.get(`/files/${id}`);
return response.data;
},
downloadFile: async (id: string): Promise<void> => {
const response = await api.get(`/files/${id}/download`, {
responseType: 'blob',
});
const blob = new Blob([response.data]);
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
const contentDisposition = response.headers['content-disposition'];
const filename = contentDisposition?.match(/filename="?([^"]+)"?/)?.[1] || 'download';
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
},
getFileUrl: async (id: string, expiresIn?: number): Promise<{ success: boolean; data: { url: string } }> => {
const response = await api.get(`/files/${id}/url`, { params: { expiresIn } });
return response.data;
},
updateFile: async (id: string, data: Partial<Pick<File, 'name' | 'category' | 'tags'>>): Promise<{ success: boolean; data: File }> => {
const response = await api.put(`/files/${id}`, data);
return response.data;
},
deleteFile: async (id: string): Promise<{ success: boolean; message: string }> => {
const response = await api.delete(`/files/${id}`);
return response.data;
},
processImage: async (id: string, options: ProcessImageOptions): Promise<void> => {
const response = await api.post(`/files/${id}/process`, options, {
responseType: 'blob',
});
const blob = new Blob([response.data]);
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `processed-${id}.jpg`;
a.click();
window.URL.revokeObjectURL(url);
},
};