본문 바로가기
Python

AWS S3 이미지 파일 압축하여 다운로드 하기

by Shark_상어 2023. 6. 20.
728x90

필자는 Django 와 S3를 사용하여 용량이 높고, 대량의 이미지들을 서버에 저장하지 않고 압축파일로 만들어
클라이언트를 제공하기 위하여 제작된 코드임을 먼저 설명 드리고 싶다.

 

1. 요구사항
1) 실행 중인 서버에 이미지들을 저장 하지 아니한다.

2) 25~50장 사진들과 총 용량은 3GB이상 기준 이며 압축된 파일로 클라이언트가 받을수 있도록 해야한다.

3) 한국이 아닌 타국에서도 속도 보장 되어야 하며 이미지 파일들이 깨지지 않도록 해야 한다(비동기로 재 작성 할 예정)

4) AWS SDK를 활용한다.

5) 다수의 사용자가 동시에 진행시 서버에 무리가 가지 않도록 해야한다. (로드밸런싱)

@login_required
def download_image(request):
    try:
        if request.method == "POST":
            # 클라이언트 요청에서 이미지 파일 정보 가져오기
            data = json.loads(request.body)
            customer_product_image_id = data.get("customer_product_image_id")

            # 이미지 ID로부터 S3 URL 가져오기
            try:
                photo_upload = Photo_upload.objects.get(id=customer_product_image_id)
                s3_url = photo_upload.s3_url
            except Photo_upload.DoesNotExist:
                return HttpResponse("이미지를 찾을 수 없습니다.")

            session = boto3.Session(
                aws_access_key_id=settings.S3_ACCESS_KEY, aws_secret_access_key=settings.S3_SECRET_KEY
            )

            # S3 버킷 정보 설정
            bucket_name = settings.S3_BUCKET_NAME
            prefix = s3_url

            # S3 객체들 가져오기
            s3 = session.client("s3")

            try:
                response = s3.list_objects_v2(Bucket=bucket_name, Prefix=prefix)
                objects = response.get("Contents", [])
                image_objects = [obj for obj in objects if obj["Key"].lower().endswith((".jpg", ".jpeg", ".png", ".gif"))]
            except ClientError as e:
                return HttpResponse("이미지를 찾을 수 없습니다.")

            # 이미지 파일들을 압축하여 ZIP 파일 생성
            zip_buffer = io.BytesIO()
            with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file:
                for image_obj in image_objects:
                    try:
                        # S3에서 이미지 파일 가져오기
                        response = s3.get_object(Bucket=bucket_name, Key=image_obj["Key"])
                        image_data = response["Body"].read()

                        # 이미지 파일 이름에서 경로 제거하여 압축 파일에 추가
                        image_name = os.path.basename(image_obj["Key"])
                        zip_file.writestr(image_name, image_data)
                    except ClientError as e:
                        continue

            # ZIP 파일 다운로드 응답 생성
            zip_buffer.seek(0)
            mime_type = settings.MIME_TYPES[0][1]  # Extracting the MIME type from the list
            response = HttpResponse(zip_buffer, content_type=mime_type)  # MIME 타입 설정
            response["Content-Disposition"] = 'attachment; filename="images.zip"'

            return response

        return HttpResponse("Invalid request method")
    except Exception as e:
        return HttpResponse("None")

728x90