Files
frontend/apps/cm/src/shared/lib/use-tus.ts
T

91 lines
2.5 KiB
TypeScript

import { useEffect, useState } from "react";
import { type HttpResponse, Upload } from "tus-js-client";
import { AUTH_USER_ID, CLAIM_NAME, ENDPOINT } from "../config";
import { useAttachmentStore } from "./use-attachment-store";
import { useAlertStore } from "./use-alert-store";
import { getCookie } from "./cookie";
type TusProps = {
accept?: string;
};
export const useTus = ({ accept }: TusProps = {}) => {
const alert = useAlertStore((state) => state.setMessage);
const { attachmentFileCode, setAttachmentFileCode } = useAttachmentStore(
(state) => state,
);
const [file, setFile] = useState<File | null>(null);
const [upload, setUpload] = useState<Upload | null>(null);
const [response, setResponse] = useState<HttpResponse | null>(null);
const [progress, setProgress] = useState<number>(0);
const [isValid, setIsValid] = useState<boolean>(false);
const metadata = {
filename: file?.name ?? "",
filetype: file?.type ?? "",
atflCd: attachmentFileCode,
};
const validFileType = (file: File) => {
const allowedExtensions = accept?.split(",") ?? [];
const fileName = file.name;
const fileExtension = fileName
.substring(fileName.lastIndexOf("."))
.toLowerCase();
if (!allowedExtensions.includes(fileExtension)) {
alert("파일 형식이 올바르지 않습니다.");
setIsValid(false);
return false;
}
setIsValid(true);
return true;
};
const createUpload = () => {
return new Upload(file!, {
endpoint: `${ENDPOINT.ATTACH_SERVICE.TUS_UPLOAD}`,
chunkSize: 10 * 1024 * 1024,
headers: {
[CLAIM_NAME]: getCookie(CLAIM_NAME) ?? "",
[AUTH_USER_ID]: getCookie(AUTH_USER_ID) ?? "",
},
metadata,
onError(error) {
throw new Error(`Failed because: ${error}`);
},
onProgress(bytesUploaded, bytesTotal) {
const percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2);
setProgress(parseInt(percentage));
},
onAfterResponse(req, res) {
const fileInfo = res.getHeader("X-File-Info");
if (fileInfo === undefined || fileInfo === null) return;
setAttachmentFileCode(JSON.parse(fileInfo)?.atflCd ?? "");
setResponse(res);
},
});
};
useEffect(() => {
if (!file) return;
if (!validFileType(file)) return;
const upload = createUpload();
upload.start();
setUpload(upload);
}, [file]);
return {
file,
upload,
response,
progress,
isValid,
setFile,
};
};