유저가 프로필 이미지를 설정하기 위해 이미지 파일을 django 서버에 업데이트 요청했을 때 S3에 올린 다음 올린 URL을 User 테이블의 user_profile_image에 업데이트합니다. 나중에 유저가 프로필 정보를 요구할 때 User 테이블에 질의하면 user_profile_image에서 URL을 얻을 수 있으므로 모바일에서는 그 URL을 가지고 이미지에 접근할 수 있습니다.
생성 후 서버에서 S3에 접근하기 위해 액세스키를 받았습니다.
...
AWS_ACCESS_KEY_ID = secrets["AWS_ACCESS_KEY_ID"]
AWS_SECRET_ACCESS_KEY = secrets["AWS_SECRET_ACCESS_KEY"]
AWS_STORAGE_BUCKET_NAME = 'capstone28subway'
AWS_S3_REGION_NAME = 'ap-northeast-2'
...
다른 파일에서 필요한 AWS 관련 데이터입니다. class UserProfileUploadSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ["user_nickname", "user_profile_image"]
def update(self, instance, validated_data):
instance.user_profile_image = validated_data["user_profile_image"]
instance.save()
return instance
class UserUploadImageView(APIView):
def post(self, request):
image = request.FILES["image"]
user_nickname = request.data["user_nickname"]
data = {}
if User.objects.filter(user_nickname=user_nickname):
user = User.objects.get(user_nickname=user_nickname)
url = S3ImageUploader(image).upload()
serializer = UserSerializer(user,{"user_nickname":user_nickname, "user_profile_image":url})
if serializer.is_valid():
serializer.save()
data["url"] = url
return Response(data)
else:
data["error"] = "Wrong Request"
return Response(data, status=status.HTTP_400_BAD_REQUEST)
else:
data["error"] = "User is not exist"
return Response(data, status=status.HTTP_400_BAD_REQUEST)
유저 닉네임을 받아서 유저 인스턴스를 찾고 S3에 이미지를 업로드한 후에 user_profile_image을 수정합니다.class S3ImageUploader:
def __init__(self, file):
self.file = file
def upload(self):
s3_client = boto3.client(
's3',
aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
region_name=settings.AWS_S3_REGION_NAME
)
i = str(uuid.uuid4())
response = s3_client.upload_fileobj(self.file, settings.AWS_STORAGE_BUCKET_NAME, i)
return f'https://{settings.AWS_STORAGE_BUCKET_NAME}.s3.{settings.AWS_S3_REGION_NAME}.amazonaws.com/{i}'
IAM 사용자의 엑세스 키를 통해서 S3_client를 받은 후에 고유한 이름값을 붙여 S3에 업로드합니다. 그리고 리턴 값은 이미지 파일에 접근할 수 있는 URL입니다.