feat: 첨부파일 다운로드 작업

This commit is contained in:
2025-05-07 13:22:16 +09:00
parent 1bf2919a09
commit f5e7601d54
5 changed files with 121 additions and 4 deletions
@@ -1,17 +1,73 @@
"use client";
import dayjs from "dayjs";
import type { AxiosResponse } from "axios";
import { useEffect, useState, useTransition } from "react";
import { useQuery } from "@tanstack/react-query";
import { Button, Skeleton } from "@common/components";
import { PostApi } from "@/entities/post";
import { AttachmentApi } from "@/entities/attachment";
import { ENDPOINT } from "@/shared/config";
import { PostAction } from "./post-action";
function Post({ bbsId, pstNo }: { bbsId: string; pstNo: string }) {
const [isPending, startTransition] = useTransition();
const [filename, setFilename] = useState("");
const [downloadResponse, setDownloadResponse] =
useState<AxiosResponse | null>(null);
const { data: postData } = useQuery({
queryKey: [ENDPOINT.BOARD_SERVICE.POSTS],
queryFn: () => PostApi.getPostInfo(bbsId, pstNo),
});
useEffect(() => {
if (!postData?.atflCd) return;
startTransition(async () => {
try {
let filename = "";
const response = await AttachmentApi.downloadAttachmentByAtflCd(
postData.atflCd,
);
setDownloadResponse(response);
const contentDisposition = response.headers["content-disposition"];
if (contentDisposition) {
const filenameMatch = contentDisposition.match(
/filename\*=UTF-8''([^;]+)/,
);
if (filenameMatch && filenameMatch[1]) {
filename = decodeURIComponent(filenameMatch[1]);
}
}
setFilename(filename);
} catch {
setFilename("");
}
});
}, [postData?.atflCd]);
const handleDownload = async () => {
if (isPending || !downloadResponse) return;
try {
startTransition(() => {
const blob = new Blob([downloadResponse.data]);
const url = window.URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = filename || "download";
document.body.appendChild(link);
link.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(link);
});
} catch (error) {
console.error(error);
}
};
return (
<PostAction bbsId={bbsId} pstNo={pstNo}>
<div className="card card-border !p-8">
@@ -36,7 +92,23 @@ function Post({ bbsId, pstNo }: { bbsId: string; pstNo: string }) {
/>
<hr className="mt-8" />
<div className="flex items-center gap-4 p-8">
<span>첨부파일</span>
<span className="font-bold">첨부파일</span>
{isPending ? (
<Skeleton className="h-[2.5rem] w-[20rem]" />
) : (
filename && (
<Button
size="sm"
color="white"
className="flex w-fit items-center gap-2"
onClick={handleDownload}
disabled={isPending}
>
<i className="diveicon di-download" />
<span>{filename}</span>
</Button>
)
)}
</div>
</div>
</PostAction>