PWA에서 다운로드 버튼을 클릭하면 사용자의 갤러리에 이미지가 저장되도록 하는 것이 구현 목표이다.
일반적인 웹에서의 다운로드 링크로는 한계가 있었다.
💾 이미지 다운 구현
1. Blob 객체로 이미지 데이터 처리
현재 나는 백엔드에서 받은 이미지 url을 가지고 있는 상황이다.
이미지 url을 Blob으로 변환한다.
2. 패키지 설치
file-saver 라이브러리를 활용해 Blob을 png로 변환한다.
나 같은 경우는 파일명에 .png로 지정해 주어 png로 저장되지만, .jpg로 지정하면 jpg로 저장된다.
yarn add file-saver
3. 파일 저장 구현
const handleDownload = async () => {
try {
const response = await fetch(imageUrl);
const blob = await response.blob();
saveAs(blob, `KidWe_${Date.now()}.png`);
} catch (error) {
toast.error('이미지 저장 실패');
}
};
🚨 에러 발생
Access to fetch at 'https://common-kidwe-image.s3.ap-northeast-2.amazonaws.com/001b5fb1-9ea7-46a7-82b6-9a0f9aa7d31f.png' from origin 'http://localhost:3030' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
🥁 해결 과정
const response = await fetch(imageUrl, {mode: 'no-cors'});
사실 이렇게 우회해 봤는데 이미지 저장이 되는 줄 알았으나 파일을 열어보니 아래처럼 떴다.. 하긴 당연히 안 되는 게 맞지
CORS 허용해주자!
이미지를 s3 bucket에 저장해서 쓰고 있었는데, s3에서 우리 도메인 요청을 허용해야 한다.
근데... 다 허용했는데도 안 됐다.............. 대체 왜지..?
캐싱할 때 CORS 헤더 누락
찾아보니 브라우저가 이미지를 캐시에 저장할 때 CORS 헤더 없이 저장하여 캐시에서 가져올 때 CORS에 의해 차단되는 것 같다.
아래 코드처럼 imageUrl 뒤에 ?not-from-cache-please를 추가했더니 해결되었다.
const handleDownload = async () => {
try {
const response = await fetch(`${imageUrl}?not-from-cache-please`, {
method: 'GET',
mode: 'cors',
});
const blob = await response.blob();
saveAs(blob, `KidWe_${Date.now()}.png`);
} catch (error) {
toast.error('이미지 저장 실패');
}
};
📝 참고글
반응형
'Library & Runtime > React' 카테고리의 다른 글
camelCase 요청 데이터를 snake_case로 변환하기 (0) | 2024.11.05 |
---|---|
snake_case 응답 데이터를 camelCase로 변환하기 (0) | 2024.11.04 |
[React] React Router 총정리 (0) | 2024.08.26 |
[React] React Quill 사용하기 & HTML 렌더링하기 (0) | 2024.08.21 |
[React] Vite + TypeScript + PWA 프로젝트 생성하기 (1) | 2024.07.30 |