여러 사진 중 일부 사진의 허용 사이즈 초과로 실패한 경우에 대해
안녕하세요 정환님! 항상 강의 감사한 마음으로 잘 듣고 있습니다. 이번 이미지 업로드 구현하기2 강의를 끝까지 듣고 따라하던중 스토리지에 이미지 업로드 병렬로 요청 시 제가 업로드 시도한 이미지 4장 중 1장이 허용 사이즈 초과로 스토리지 업로드 요청이 실패 했었는데요, 당연히 이미지 업로드 실패로
await deletePost(post.id);가 호출되 post.id를 받기위해 먼저 생성한 포스트가 삭제되어 포스트 자체가 안된것처럼 동작했습니다. 근데 storage에서는 업로드 요청이 실패된 이미지를 제외하고 나머지 3장의 이미지가 저장이 되어있더라고요!
간단하게 4장 병렬 이미지 업로드 요청 > 3장 성공 1장 실패 > 이미지 업로드 일부 실패로 포스트 삭제 > storage에는 성공한 3장의 이미지만 존재, 포스트는 없음
이 상태여서 혼자 찾아봐서 추가해봤는데 맞는지도 궁금하고 맞다면 다른 분들도 비슷한 상황에서 도움이 될까 싶어 올립니다!!
images.ts 파일에 스토리지에서 이미지 삭제하는 비동기 요청 함수
export async function deleteImages(filePath: string[]) {
const { data, error } = await supabase.storage
.from(BUCKET_NAME)
.remove(filePath);
if (error) throw error;
return data;
}
post.ts > createPostWithImages 함수 에서 try, catch문 밖에 업로드전 생성한 filePath 저장할 배열 값을 갖는 변수 선언
const uploadedFilePaths: string[] = [];
const imageUrls = await Promise.all(
images.map((image) => {
const fileExtension = image.name.split(".").pop() || "webp";
const fileName = `${Date.now()}-${crypto.randomUUID()}.${fileExtension}`;
const filePath = `${userId}/${post.id}/${fileName}`;
uploadedFilePaths.push(filePath);
return uploadImage({
file: image,
filePath,
});
}),
);uploadImage 리턴 전에 생성한 filePath값 저장
catch문에서
if (uploadedFilePaths.length > 0) {
await deleteImages(uploadedFilePaths);
}조건문 추가
최종 결과
병렬 요청중 일부의 요청이 파일의 크기 초과 등으로 실패하면
throw error >
await deletePost(post.id);
if (uploadedFilePaths.length > 0) {
await deleteImages(uploadedFilePaths);
}
throw error;
포스트 삭제, 스토리지 이미지 삭제
글을 잘 못써서 가독성이 떨어지는 부분은 양해부탁드립니다..
답변 2
1
반영 코드 도움되시는분 있으실까 첨부합니다
export async function createPostWithImages({
content,
images,
userId,
}: {
content: string;
images: File[];
userId: string;
}) {
// 1. 새로운 포스트 생성
const post = await createPost(content);
if (images.length === 0) return post;
const uploadedFilePaths: string[] = [];
try {
// 2. 이미지 업로드
const imageUrls = await Promise.all(
images.map((image) => {
const fileExtension = image.name.split(".").pop() || "webp";
const fileName = `${Date.now()}-${crypto.randomUUID()}.${fileExtension}`;
const filePath = `${userId}/${post.id}/${fileName}`;
uploadedFilePaths.push(filePath);
return uploadImage({
file: image,
filePath,
});
}),
);
// 3. 포스트 테이블 업데이트
const updatedPost = await updatePost({
id: post.id,
image_urls: imageUrls,
});
return updatedPost;
} catch (error) {
await Promise.all([
deletePost(post.id),
uploadedFilePaths.length > 0
? deleteImages(uploadedFilePaths)
: Promise.resolve(),
]);
throw error;
}
}
0
안녕하세요 재환님 이정환입니다.
앗! 그렇네요 🥲 이런 이슈가 있을 수 있겠군요
해당 이슈를 해결하려면 재환님이 말씀해주신 대로 catch 문에서 업로드 된 이미지 전체를 삭제하는 로직을 추가해주시면 됩니다!
한가지 코멘트를 남기자면 await deletePost와 await deleteImages는 Promise.all을 통해 묶어 병렬처리하면 더 깔끔할 것 같아요!
회원가입 구현 (구현 후 최종 화면 출력 X)
0
65
2
(6.11) 회원가입시 프로필 정보 자동 생성하기 Q. 호출 순서 문의
0
56
1
명시적 타입 선언(콜론 타입 선언)과 as 타입 단언 차이
0
58
2
useMutation 적용 후 새로운 글 등록시 content가 안보여요
0
70
2
6.8 zustand 세션 질문입니다.
0
110
2
next.js 강의에서도 리액트 라이브러리들을 다뤄주시나요?
0
93
2
shadcn에서 radix ui와 base ui 차이는 뭔가요?
1
406
2
updateTodo 함수 생성시 화살표 함수 사용 안하는 이유
0
84
2
4.11 바로 투두 삭제가 안됨 질문
0
102
3
매개변수 updatedTodo 관련 질문
0
79
3
인증 정보가 만료되었을 때 라우트 가드 처리가 궁금합니다!
0
91
2
supabase를 사용하지 않을 경우 세션 데이터의 변경을 감지하고 스토어에 보관하는 방법이 궁금합니다!
0
85
2
4.6 id를 string으로 변경시 오류
0
74
2
리액트 타입스크립트 관련 질문있습니다.
0
71
1
소셜 로그인 구현하기 관련하여 질문이 있습니다!
0
108
2
ui 파일 질문드립니다.
0
90
1
tanstack query devtools에서 질문있습니다!
0
75
2
댓글 삭제 시 isPending 질문
0
72
2
두번째 예외상황에 대해 질문있습니다!
0
70
1
리액트 쿼리 질문입니다
1
85
2
개발자도구에서 components 가 안보입니다.
0
109
3
state 관리에 대한 정리
0
88
3
[(2.4) Shadcn/ui를 소개합니다] 강의 Shadcn 세팅 관련 질문 있습니다.
0
212
3
like 테이블에서 왜 create_at이 필요한지 궁금합니다.
0
87
1





