const downloadSelectedImages = async () => {
selectedImages.forEach((url, index) => {
const link = document.createElement('a');
link.href = url;
link.download = `phototalk_${index + 1}.jpg`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
};
a 태그의 download 속성으로 href에 지정한 파일을 다운받을 수 있다.
한 장을 다운 받을 때는 정상적으로 작동하지만, 여러 장을 다운로드 받으면 마지막에 선택된 이미지만 다운로드된다.
→ a.click()을 반복 호출하면, 대부분의 브라우저가 보안상 1개만 허용하거나 무시하기 때문
const delay = (ms: number) => new Promise((res) => setTimeout(res, ms));
const downloadSelectedImages = async () => {
for (let i = 0; i < selectedImages.length; i++) {
const url = selectedImages[i];
const link = document.createElement('a');
link.href = url;
link.download = `phototalk_${i + 1}.jpg`
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
// 브라우저가 처리할 시간을 줘야 여러 개가 잘 동작함
await delay(500);
}
};
but, 이미지 수가 많으면 느려짐.
이 방법 말고 zip으로 압축받는 방법이 있는데,
사용자를 고려했을 때 3~4장일 경우에도 zip으로 압축되면 불편할 것 같다고 생각했다.
따라서, 이미지 수가 많을 때만 zip으로 다운받게 하고, 적당하면 순차 다운받게 하는 방법 선택
zip으로 다운받으려고 했더니,, CORS 에러가 발생했다.
S3 이미지 URL을 JS에서 가져오려고 하면, S3가 브라우저 요청을 허용하지 않는 것이다.
즉, S3에서 Access-Control-Allow-Origin
헤더가 없기 때문에 브라우저가 JS에서 fetch
요청을 차단한다.
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET"],
"AllowedOrigins": ["*"],
"ExposeHeaders": [],
"MaxAgeSeconds": 3000
}
]
AWS S3 → 버킷 → “권한” 탭 → “CORS 설정”
link.download
const fileName = (index: number) => `phototalk_${index + 1}.jpg`;
export const downloadImage = (url: string, index: number) => {
const link = document.createElement('a');
link.href = url;
link.download = fileName(index);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
"ExposeHeaders": ["Content-Disposition"],
const fileName = (index: number) => `phototalk_${index + 1}.jpg`;
export const downloadImage = (url, index) => {
fetch(url)
.then(response => response.blob()) // 파일을 Blob으로 변환
.then(blob => {
const link = document.createElement('a'); // 링크 요소 생성
link.href = URL.createObjectURL(blob); // Blob을 URL로 변환
link.download = fileName; // download 속성으로 파일명 설정
document.body.appendChild(link); // DOM에 추가
link.click(); // 다운로드 트리거
document.body.removeChild(link); // DOM에서 삭제
})
.catch(err => console.error('Download error:', err));
};
Blob을 사용하면 URL을 클라이언트 측에서 처리할 수 있다.
- Blob? 실제 바이너리 데이터를 포함하는 객체로, 파일의 실제 내용에 접근할 수 있게 해준다.
fetch(url)
을 사용하여 서버에서 파일을 가져온 뒤, 그 파일을 blob()
으로 처리하고 URL.createObjectURL()
을 사용해 클라이언트 측에서 Blob 객체를 가리키는 URL을 생성한다.
이 URL은 로컬에서 처리되는 객체로, 브라우저의 다운로드 제한을 우회할 수 있다.
즉, 서버가 CORS 정첵을 허용하지 않아도 클라이언트에서 다운로드 가능하게 한다.
따라서, 웹 브라우저에서 직접 파일을 다운로드 받기 위해서는, URL에서 Blob으로 바꾸고 다시 URL로 바꿔서 다운로드 링크를 만드는 방식이 필요하다.
- URL -> Blob: 이미지의 URL을 통해 해당 이미지 데이터를
Blob
형태로 변환.- Blob -> URL:
URL.createObjectURL(blob)
을 사용해 Blob 데이터를 가리키는 URL을 생성하고, 이 URL을<a>
태그의href
속성에 넣고, 다운로드 링크를 만든다.- URL -> 다운로드: 링크를 클릭하면 브라우저는 이 URL을 통해 파일을 다운로드.
const AWS = require('aws-sdk');
const s3 = new AWS.S3();
const params = {
Bucket: 'your-bucket-name',
Key: 'example.jpg', // 파일 키
Body: fileBuffer,
ContentDisposition: 'attachment; filename="custom_filename.jpg"' // 파일 이름 설정
};
s3.upload(params, function(err, data) {
if (err) {
console.log("Error uploading file:", err);
} else {
console.log("File uploaded successfully:", data);
}
});