사용자의 요청을 처리하는 기능 구현 중 사용자의 첨부 자료를 다운로드하여 확인해야하는 기능이 필요하다. React에서 파일을 다운로드 하는 방법을 구현하고 정리해보자.
${serverUrl}${creatorDetailData.file_src}
{
...
"affiliation": "Tesggr",
"grade": "초3",
"nickname": "스파냐",
"name": "테스트",
...
"state": 1,
"file_src": "/creator/20069242-dec1-4284-be9c-2bc030ce0aa9.jpg",
"category": [24],
...
}
const handleFileDownload = () => {
window.open(`${serverUrl}/${creatorDetailData.file_src}`);
};
<a>
요소의 download<a>
요소의 다운로드 속성을 사용한다. const handleFileDownload = () => {
const a = document.createElement("a");
a.href = `${process.env.NEXT_PUBLIC_BASIC_URL}${creatorDetailData.file_src}`;
a.download = creatorDetailData.file_src.split("/").pop() || "download";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
CORS
문제로 다른 출처의 URL을 가리키면 보안상의 이유로 download 속성을 무시하고 파일을 새 탭이나 창에서 열도록 동작함을 알 수 있다.CORS는 SOP의 제한을 안전하게 완화하기 위한 방법이다.
blob
형태로 가져오고 이 blob
을 이용해 브라우저에서 직접 다운로드할 수 있는 URL을 생성할 수 있다.const handleFileDownload = () => {
setIsDownloading(true);
const fileUrl = `${serverUrl}${creatorDetailData.file_src}`;
fetch(fileUrl)
.then((response) => response.blob())
.then((blob) => {
const url = window.URL.createObjectURL(new Blob([blob]));
const a = document.createElement("a");
a.href = url;
a.download = creatorDetailData.file_src.split("/").pop() || "download";
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
setIsDownloading(false);
})
.catch((error) => {
console.error("파일 다운로드 오류:", error);
setIsDownloading(false);
});
};
export function CreatorSettingForm({
creatorDetailData,
categoryList,
}: CreatorSettingFormProps) {
const [isDownloading, setIsDownloading] = useState(false);
const handleFileDownload = () => {
setIsDownloading(true);
const fileUrl = `${creatorDetailData.file_src}`;
client // AxiosInstance
.get(fileUrl, { responseType: "blob" })
.then((response) => {
const url = window.URL.createObjectURL(new Blob([response.data]));
const a = document.createElement("a");
a.href = url;
a.download = creatorDetailData.file_src.split("/").pop() || "download";
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
setIsDownloading(false);
})
.catch((error) => {
console.error("파일 다운로드 오류:", error);
setIsDownloading(false);
});
};
return (
<div className="space-y-6">
<div>
<h3 className="text-lg font-medium sticky">크리에이터 신청</h3>
<CreatorDetailTable
creatorDetailData={creatorDetailData}
categoryList={categoryList}
/>
<div>
{isDownloading ? (
<Button disabled>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
다운로드 중
</Button>
) : (
<Button onClick={handleFileDownload}>첨부파일 다운로드</Button>
)}
</div>
</div>
</div>
);
}
zip 파일 다운로드 검색해보다가 봤는데 사랑대디네요ㅋㅋㅋㅋ 잘보고 갑니당