2025-09-05 12:04:13 +09:00
|
|
|
import { apiClient } from "./client";
|
|
|
|
|
|
|
|
|
|
export interface FileInfo {
|
|
|
|
|
id: string;
|
|
|
|
|
name: string;
|
|
|
|
|
size: number;
|
|
|
|
|
type: string;
|
|
|
|
|
extension: string;
|
|
|
|
|
uploadedAt: string;
|
|
|
|
|
lastModified: string;
|
|
|
|
|
serverPath?: string;
|
|
|
|
|
serverFilename?: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface FileUploadResponse {
|
|
|
|
|
success: boolean;
|
|
|
|
|
message: string;
|
|
|
|
|
files: FileInfo[];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface FileDownloadParams {
|
|
|
|
|
fileId: string;
|
|
|
|
|
serverFilename: string;
|
|
|
|
|
originalName: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 파일 업로드
|
|
|
|
|
*/
|
|
|
|
|
export const uploadFiles = async (files: FileList): Promise<FileUploadResponse> => {
|
|
|
|
|
const formData = new FormData();
|
|
|
|
|
|
|
|
|
|
Array.from(files).forEach((file) => {
|
|
|
|
|
formData.append("files", file);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const response = await apiClient.post("/files/upload", formData, {
|
|
|
|
|
headers: {
|
2025-09-05 21:52:19 +09:00
|
|
|
"Content-Type": undefined, // axios가 자동으로 multipart/form-data를 설정하도록
|
2025-09-05 12:04:13 +09:00
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return response.data;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 파일 다운로드
|
|
|
|
|
*/
|
|
|
|
|
export const downloadFile = async (params: FileDownloadParams): Promise<void> => {
|
|
|
|
|
try {
|
|
|
|
|
console.log("📥 downloadFile 호출:", params);
|
|
|
|
|
|
|
|
|
|
const response = await apiClient.get(`/files/download/${params.fileId}`, {
|
|
|
|
|
params: {
|
|
|
|
|
serverFilename: params.serverFilename,
|
|
|
|
|
originalName: params.originalName,
|
|
|
|
|
},
|
|
|
|
|
responseType: "blob", // 파일 다운로드를 위해 blob 타입으로 설정
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
console.log("📥 다운로드 응답:", response);
|
|
|
|
|
|
|
|
|
|
// Blob URL 생성
|
|
|
|
|
const blob = new Blob([response.data]);
|
|
|
|
|
const url = window.URL.createObjectURL(blob);
|
|
|
|
|
|
|
|
|
|
// 다운로드 링크 생성 및 클릭
|
|
|
|
|
const link = document.createElement("a");
|
|
|
|
|
link.href = url;
|
|
|
|
|
link.download = params.originalName;
|
|
|
|
|
document.body.appendChild(link);
|
|
|
|
|
link.click();
|
|
|
|
|
|
|
|
|
|
// 정리
|
|
|
|
|
document.body.removeChild(link);
|
|
|
|
|
window.URL.revokeObjectURL(url);
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("파일 다운로드 오류:", error);
|
|
|
|
|
throw new Error("파일 다운로드에 실패했습니다.");
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 파일 삭제
|
|
|
|
|
*/
|
|
|
|
|
export const deleteFile = async (fileId: string, serverFilename: string): Promise<void> => {
|
|
|
|
|
const response = await apiClient.delete(`/files/${fileId}`, {
|
|
|
|
|
data: { serverFilename },
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!response.data.success) {
|
|
|
|
|
throw new Error(response.data.message || "파일 삭제에 실패했습니다.");
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 파일 정보 조회
|
|
|
|
|
*/
|
|
|
|
|
export const getFileInfo = async (fileId: string, serverFilename: string) => {
|
|
|
|
|
const response = await apiClient.get(`/files/info/${fileId}`, {
|
|
|
|
|
params: { serverFilename },
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return response.data;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 파일 업로드 및 JSON 데이터 생성
|
|
|
|
|
* InteractiveScreenViewer에서 사용할 통합 함수
|
|
|
|
|
*/
|
|
|
|
|
export const uploadFilesAndCreateData = async (files: FileList) => {
|
|
|
|
|
try {
|
|
|
|
|
// 1. 파일 업로드
|
|
|
|
|
const uploadResponse = await uploadFiles(files);
|
|
|
|
|
|
|
|
|
|
if (!uploadResponse.success) {
|
|
|
|
|
throw new Error(uploadResponse.message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2. JSON 데이터 구조 생성
|
|
|
|
|
const fileData = {
|
|
|
|
|
files: uploadResponse.files.map((file) => ({
|
|
|
|
|
id: file.id,
|
|
|
|
|
name: file.name,
|
|
|
|
|
size: file.size,
|
|
|
|
|
type: file.type,
|
|
|
|
|
extension: file.extension,
|
|
|
|
|
uploadedAt: file.uploadedAt,
|
|
|
|
|
lastModified: file.lastModified,
|
|
|
|
|
serverFilename: file.serverFilename, // 다운로드에 필요
|
|
|
|
|
})),
|
|
|
|
|
totalCount: uploadResponse.files.length,
|
|
|
|
|
totalSize: uploadResponse.files.reduce((sum, file) => sum + file.size, 0),
|
|
|
|
|
lastModified: new Date().toISOString(),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
success: true,
|
|
|
|
|
data: fileData,
|
|
|
|
|
message: uploadResponse.message,
|
|
|
|
|
};
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("파일 업로드 및 데이터 생성 오류:", error);
|
|
|
|
|
throw error;
|
|
|
|
|
}
|
|
|
|
|
};
|
2025-09-06 00:16:27 +09:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 테이블 연결된 파일 조회
|
|
|
|
|
*/
|
|
|
|
|
export const getLinkedFiles = async (
|
|
|
|
|
tableName: string,
|
|
|
|
|
recordId: string,
|
|
|
|
|
): Promise<{
|
|
|
|
|
success: boolean;
|
|
|
|
|
files: any[];
|
|
|
|
|
totalCount: number;
|
|
|
|
|
targetObjid: string;
|
|
|
|
|
}> => {
|
|
|
|
|
try {
|
|
|
|
|
console.log("📎 연결된 파일 조회:", { tableName, recordId });
|
|
|
|
|
|
|
|
|
|
const response = await apiClient.get(`/files/linked/${tableName}/${recordId}`);
|
|
|
|
|
|
|
|
|
|
console.log("✅ 연결된 파일 조회 성공:", response.data);
|
|
|
|
|
|
|
|
|
|
return response.data;
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error("연결된 파일 조회 오류:", error);
|
|
|
|
|
throw new Error("연결된 파일 조회에 실패했습니다.");
|
|
|
|
|
}
|
|
|
|
|
};
|