회사 프로젝트에서 s3에 업로드 되어있는 이미지 url을 서버로부터 받아서 화면에 뿌려준뒤
다운로드 버튼을 클릭하면 해당 이미지를 다운로드 받는 기능을 구현하고 있었다.
보통 이미지를 다운받는 코드라 하면 아래와같이 간단하게 구현할 수 있다.
<a href = "/이미지 경로" download="파일이름.jpg">이미지 다운로드 버튼</a>
또는
const handleDownloadClick = (url: string) => {
const aTag = document.createElement("a");
aTag.href = url;
aTag.download = "파일이름.jpg";
aTag.click();
}
하지만 보안 이슈로 인하여 2018년 말부터 다운로드할 리소스가 동일한 출처 또는 동일한 서버에서 제공되지 않은 경우
링크를 클릭해도 다운로드가 트리거되지 않고 해당 이미지 주소로 이동만 될 뿐이였다.
이를 해결하는 방법으로 s3 url을 blob URL형식으로 바꿔주면 된다.
const s3ImageURL = "https..."
const handleDownloadClick = (url: string) => {
fetch(s3URL, {
method: "GET",
})
.then((res) => {
return res.blob();
})
.then((blob) => {
const blobURL = URL.createObjectURL(blob);
const aTag = document.createElement("a");
aTag.href = blobURL;
aTag.download = "image.jpg";
aTag.click();
})
.catch((e) => {
console.error(e);
});
};
이미지 주소에 요청을 하였을때 s3 버킷에 따로 cors 관련 처리를 해주지 않았다면
cors 에러가 나타날 것이다.
이를 해결하는 방법은 다음과 같다.
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"HEAD",
"GET",
"PUT",
"POST",
"DELETE"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [
"ETag"
]
}
]
이 예시에서는 origins 설정을 모든 출처 접근 허용인 "*"로 설정하였지만 원하는 페이지 주소로 따로 설정을 하면된다.
하지만 여전히 cors 에러가 사라지지 않고 나타나고있었다..
찾아보니 safari나 다른 브라우저에서는 정상 작동하지만 chrome에서만 나타나는 문제였다.
그래도 해결은 해야하니 방법을 찾아보던중 cloudfront을 사용하여 cors를 우회하는 방법을 택했다.
연결할 s3 버킷을 찾아서 선택해주면 된다.
밑으로 내리면 기본 캐시 동작 섹션이 보이는데
섹션안에 캐시 키 원본 요청에서 원본 요청 정책을 CORS-S3Origin 으로 바꿔주면 된다.
그리고 배포 생성을 해준뒤 코드에서 요청주소를 s3에서 cloudfront로 바꿔주면 된다.
(배포가완료되면 배포id가 생성이 되는데 클릭하면 배포 도메인 이름을 확인할 수 있다.)
const cloudfrontImageURL = "https..."
const handleDownloadClick = (url: string) => {
fetch(cloudfrontImageURL, {
method: "GET",
})
.then((res) => {
return res.blob();
})
.then((blob) => {
const blobURL = URL.createObjectURL(blob);
const aTag = document.createElement("a");
aTag.href = blobURL;
aTag.download = "image.jpg";
aTag.click();
})
.catch((e) => {
console.error(e);
});
};
그러면 성공적으로 요청이 완료된뒤 이미지 저장도 작동하는것을 확인할 수 있다!