먼저 이미지 업로드에 필요한 boto3와 이미지 리사이징에 필요한 Pillow를 인스톨 한다.
pip install boto3
pip install Pillow
view를 작성하기에 앞서 import 해준다.
import boto3 # s3에 이미지를 업로드 할 때 필요
import uuid # 파일이름에 난수를 부여하기 위해 uuid를 사용
from PIL import Image # 이미지 리사이징에 필요한 Pillow
from io import BytesIO # Pillow로 리사이징한 이미지를 다시 Bytes화
이미지 업로드, 이미지 리사이징과 관련하여, 검색해보면 수많은 질문과 답변이 존재한다.
하나하나 적용해보고 오류를 만나고 수정하다 보니 하루가 금방 지나갔고, 그래도 원래 의도했던 대로 동작하는 코드가 남아 기록으로 남겨본다.
class ProfileUploadView(View):
s3_client = boto3.client(
's3',
aws_access_key_id = S3['Access_Key_ID'],
aws_secret_access_key = S3['Secret_Access_Key']
)
def post(self, request):
try:
image = request.FILES['filename']
[1] im = Image.open(image)
[2] im = im.resize((400, 400))
[3] buffer = BytesIO()
[4] im.save(buffer, "JPEG")
[5] buffer.seek(0)
url_generator = str(uuid.uuid4())
self.s3_client.upload_fileobj(
[6] buffer,
"bucket_name",
url_generator,
[7] ExtraArgs = {
"ContentType": 'image/jpeg'
}
)
image_url = f'{S3["Address"]}{url_generator}'
return JsonResponse({'image_url' : image_url}, status = 200)
except KeyError:
return JsonResponse({"message" : "INVALID_KEYS"}, status = 400)
이미지 리사이징이 필요 없는 경우에는 [1]~[5]를 생략한 뒤 [6]의 "buffer"를 "image"로 바꾸어 업로드하면 된다.
[1] 이미지를 열어 (Pillow가 하는 일)
[2] 리사이징 해준 뒤 (Pillow가 하는 일)
[3]~[4] BytesIO를 통해 bytes화 하여 저장하고
[5] bytes화 한 객체가 잘 저장되도록 해준다.
처음에는 [7]의 ExtraArgs 부분을 생략했었는데 파일 업로드는 정상적으로 작동 하지만, url을 클릭했을 때 브라우저에서 이미지가 보이는 것이 아니라 강제로(?) 다운로드가 되어 또 열심히 구글링을 해보았다.
무려 7년 전에 작성된 질문/답변이었지만 아직도 도움받을 수 있다는게 너무 신기했다.
참고 :
https://stackoverflow.com/questions/14150854/aws-s3-display-file-inline-instead-of-force-download
이 블로깅이 미래의 나와 미래의 누군가에게 도움이 되면 좋겠다.😌
완전 도움됐어요! 감사합니다 😌