-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #57 from Kakaotech-10/feature/image
✨ 프론트 이미지 저장(게시글)
- Loading branch information
Showing
8 changed files
with
370 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// useImageUpload.jsx | ||
import api from "./config"; | ||
import { getPresignedUrl, uploadToS3 } from "./useImageUrl"; | ||
|
||
export const useImageUpload = () => { | ||
const handleImageUpload = async (postId, files, onProgress = () => {}) => { | ||
try { | ||
// 1. 파일 검증 | ||
const validFiles = files.filter((file) => { | ||
const maxSize = 5 * 1024 * 1024; // 5MB | ||
const validTypes = ["image/jpeg", "image/png", "image/gif"]; | ||
return file.size <= maxSize && validTypes.includes(file.type); | ||
}); | ||
|
||
if (validFiles.length === 0) { | ||
throw new Error("업로드할 수 있는 파일이 없습니다."); | ||
} | ||
|
||
// 2. Presigned URL 요청 | ||
const presignedData = await getPresignedUrl( | ||
postId, | ||
validFiles.map((f) => f.name) | ||
); | ||
|
||
if (!presignedData?.urls?.length) { | ||
throw new Error("업로드 URL을 받지 못했습니다."); | ||
} | ||
|
||
// 3. S3 업로드 | ||
const uploadResults = []; | ||
const totalFiles = presignedData.urls.length; | ||
|
||
for (let i = 0; i < totalFiles; i++) { | ||
const urlInfo = presignedData.urls[i]; | ||
const file = validFiles[i]; | ||
|
||
console.log(`Uploading file ${i + 1}/${totalFiles}: ${file.name}`); | ||
|
||
const s3Url = await uploadToS3(urlInfo.url, file, (progress) => { | ||
const totalProgress = (i * 100 + progress) / totalFiles; | ||
onProgress(totalProgress); | ||
}); | ||
|
||
uploadResults.push({ | ||
fileName: urlInfo.fileName, | ||
url: s3Url, | ||
}); | ||
} | ||
|
||
// 4. 이미지 URL 저장 | ||
const response = await api.post(`/api/v1/posts/${postId}/images`, { | ||
urls: uploadResults, | ||
}); | ||
|
||
return response.data.images; | ||
} catch (error) { | ||
console.error("Image upload process failed:", error); | ||
throw error; | ||
} | ||
}; | ||
|
||
return { handleImageUpload }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import axios from "axios"; | ||
import api from "./config"; | ||
|
||
export const uploadToS3 = async (presignedUrl, file, onProgress = () => {}) => { | ||
try { | ||
console.log("Starting upload:", { | ||
fileName: file.name, | ||
fileType: file.type, | ||
fileSize: file.size, | ||
}); | ||
|
||
const response = await axios.put(presignedUrl, file, { | ||
headers: { | ||
"Content-Type": file.type, | ||
}, | ||
onUploadProgress: (progressEvent) => { | ||
if (progressEvent.total) { | ||
const percentCompleted = Math.round( | ||
(progressEvent.loaded * 100) / progressEvent.total | ||
); | ||
onProgress(percentCompleted); | ||
} | ||
}, | ||
}); | ||
|
||
console.log("Upload response:", response); | ||
|
||
// 성공 시 S3 URL 반환 | ||
const s3Url = presignedUrl.split("?")[0]; | ||
return s3Url; | ||
} catch (error) { | ||
console.error("Upload error:", error); | ||
throw new Error(`파일 업로드 실패: ${error.message}`); | ||
} | ||
}; | ||
|
||
export const getPresignedUrl = async (postId, fileNames) => { | ||
try { | ||
const response = await api.post( | ||
`/api/v1/posts/${postId}/images/presigned-url`, | ||
{ fileNames } | ||
); | ||
console.log("Presigned URL Response:", response.data); | ||
return response.data; | ||
} catch (error) { | ||
console.error("Error getting presigned URL:", error); | ||
throw new Error("사전 서명된 URL을 가져오는데 실패했습니다."); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// useSaveImage.jsx | ||
import api from "./config"; | ||
|
||
export const saveImages = async (postId, imageUrls) => { | ||
try { | ||
console.log("Saving images to backend:", { postId, imageUrls }); | ||
|
||
const response = await api.post(`/api/v1/posts/${postId}/images`, { | ||
urls: imageUrls.map((url) => ({ | ||
fileName: url.fileName, | ||
url: url.url, | ||
})), | ||
}); | ||
|
||
console.log("Backend save response:", response.data); | ||
return response.data; | ||
} catch (error) { | ||
console.error("Failed to save image URLs:", error); | ||
throw new Error("이미지 URL 저장 중 오류가 발생했습니다."); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.