
오늘은 이미지 업로드 할 때 압축해서 올리는 방법 알아봅시당
npm i browser-image-compression
yarn add browser-image-compression
import imageCompression from "browser-image-compression";
// 이미지 담을 file state const [boardImage, setBoardImage] = useState(null); // 이미지 미리보기 state const [uploadPreview, setUploadPreview] = useState([]); ... return ( <ImageUploadBox> <label htmlFor="image" ref={uploadBoxRef}> <div className="textBox"> <h4>클릭하여 업로드</h4> <span>권장사항: 5MB 이하 고화질</span> </div> <BsUpload className="uploadBtn" /> </label> <input type="file" accept="image/*" id="image" ref={imageRef} onChange={onChangeImage} /> <ImagePreview> <img src={uploadPreview} alt="previewImage" /> </ImagePreview> </ImageUploadBox> )
const onChangeImage = e => {
setBoardImage(e.target.files[0]);
let reader = new FileReader();
if (e.target.files[0]) {
reader.readAsDataURL(e.target.files[0]);
}
reader.onloadend = () => {
const previewImgUrl = reader.result;
if (previewImgUrl) {
setUploadPreview(previewImgUrl);
}
};
};
이걸 라이브러리 써서 압축해봅시당
const imageCompress = async (e) => {
let file = e.target?.files[0]
const options = {
maxSizeMB: 0.2, // 이미지 최대 용량
maxWidthOrHeight: 1920, // 최대 넓이(혹은 높이)
useWebWorker: true,
};
try {
const compressedFile = await imageCompression(file, options);
setBoardImage(compressedFile);
const promise = imageCompression.getDataUrlFromFile(compressedFile);
promise.then((result) => {
setUploadPreview(result);
})
} catch (error) {
console.log(error)
}
};
라이브러리 덕분에 아주 간편하게 압축할 수 있읍니다.
이렇게 압축한 녀석을 살펴보면,
Blob { lastModified: 1594690440635 name: "image.jpg" size: 158816 type: "image/jpeg" }이런 식으로 나옵니다.
Blob은 JavaScript에서 이미지, 사운드, 비디오와 같은 멀티미디어 데이터를 다룰 때 사용합니다.
Binary Large Object
데이터의 크기(Byte)나 MIME Type을 알아내거나, 데이터 송수신을 위한 작은 Blob 객체로 나누는 작업 등에 사용함
File 객체도 name과 lastModifiedDate 속성이 포함된 Blob 객체임
암튼 이미지 압축을 진행했으니, Base64로 변환 할거임
왜용?
왜냐면 ASCII는 데이터를 전달하기에 안전하지 않다고 합디다.
특수문자를 제외한 64개의 안전한 출력 문자로 서버에 전송 및 DB 저장을 위해 변환해줍니당
이미지 깨짐, 동영상 짤림 등을 방지하기 위해 안전한 문자로 바꿔서 서버에 전송하는거임
const imageCompress = async (e) => {
let file = e.target?.files[0]
const options = {
maxSizeMB: 0.2, // 이미지 최대 용량
maxWidthOrHeight: 1920, // 최대 넓이(혹은 높이)
useWebWorker: true,
};
try {
const compressedFile = await imageCompression(file, options);
setBoardImage(compressedFile);
const promise = imageCompression.getDataUrlFromFile(compressedFile);
promise.then((result) => {
setUploadPreview(result);
})
// FileReader
const reader = new FileReader();
reader.readAsDataURL(compressedFile);
reader.onloadend = () => {
const base64data = reader.result;
formDataHandler(base64data); // 이 함수는 밑에서 설명
}
} catch (error) {
console.log(error)
}
};
이제 이걸 formData로 만들어서 서버에 전송까지 해봅시다요
const formDataHandler = async(dataURI) => {
const byteString = atob(dataURI.split(",")[1]);
const ab = new ArrayBuffer(byteString.length);
const ia = new Uint8Array(ab);
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
const blob = new Blob([ia], {
type: "image/jpeg"
});
const file = new File([blob], "image.jpg");
const formData = new FormData();
formData.append("representative_avatar", file);
try {
const response = await {서버 전송하는 API}(formData);
console.log(response)
} catch (error) {
console.log(error);
}
}
마지막으로 axios 전송 전에 header에 보내는 데이터의 Type을 지정해주면 끝!
createBoard: (payload) => axios.post(`${BASE_URL}/boards`, payload, {
headers: {
Authorization: getCookieToken("access-token"),
// header 부분에 아래와 같이 data type을 지정해줍니다.
"Content-Type": "multipart/form-data",
},
}),
어라라,,,, 이미지 압축하는 법 공부하다가 여기까지 왔네요 @)---- 잇님 잘 보고 갑니다 ^^*