본문 바로가기
프론트엔드

[트러블 슈팅] base 64 image to Javascript File (Feat. Naver Smart Editor 2.0)

by BeforB 2022. 1. 19.
728x90

 

이번에 진행한 프로젝트 중에 스마트 에디터를 사용한 게시글 쪽에서 이슈가 폭발했다..

간단한 게시글 하나를 작성하는데도 이렇게 고려할게 많다니 이번 프로젝트를 진행하면서 많이 배운 것 같다. 😂

 

 

이건 QA 때 이슈로 올라온건 아니고 테스트하다가 발견한건데, 평소와 같이 로컬에서 테스트를 진행하다가 게시판 목록화면에 들어갔을 때 갑자기 로그가 계~~~~~~속 찍히면서 VSCode가 터져버렸다..😥

 

 

원인........

처음엔 뭔가 로직이 꼬인 줄 알고 여기저기서 에러를 찾았는데 원인은 에디터에 등록되는 이미지 문제였다. 우린 DB를 읽어올 때 로그를 띄우는데 QA팀에서 에디터에 용량이 큰 이미지를 복붙하는데 그게 base64 이미지로 등록되면서 url길이가 어마어마하게 길어진 것이다(DB를 확인해보니까 길이가 50만 얼마......)

 

 

사실 에디터에는 사진을 직접 등록하는 기능이 있고 (관련해서 구현 방법도 전에 포스팅 해놨음) 그 방법으로 등록할 경우 서버에서 새로 생성한 url로 저장되도록 구현이 되어있었다.

 

[Naver] SmartEditor 2.0으로 게시판만들기 - 3. 싱글사진 업로드하기

 Spring과 DB를 연동했으니 사진을 직접 업로드하는 기능을 구현해보려고 한다. 프로젝트를 진행할 때 이미지서버는 이미 구축되어 있었고, 에디터에서 이미지를 전달받아 S3 서버에 업로드하고

beforb.tistory.com

 

 

 

그걸로만 열심히 테스트 했는데 누군가 사진을 복붙할거라곤 생각도 못했다.. 하지만 생각해보면 아주 당연한 것ㅠㅠ 나의 실수였다..

마치 언젠가 보고 열심히 공감했던 이 짤이 다시 생각나는ㅋㅋㅋㅋㅠㅠ

 

 

 

해결

그래서!! 마지막에 내용을 저장하기 직전에 본문 속에 img 태그들을 모두 찾아서 정상 루트(?)로 등록하지 않은 base64 img를 모두 찾아 기존에 이미지를 등록하던 루트와 동일한 방식으로 이미지 서버(S3)에 이미지를 올리고, 직접 생성한 url로 변환하는 로직을 추가하였다.

 

 

 

1. 우선 같은 방식으로 전송해주기 위해 base64 이미지를 javascript의 File 객체로 변환시켜준다.

function base64toFile(content) {

    // 스마트 에디터에서 content 값이 "~~"와 같은 text 타입으로 넘어온다.
    let div = document.createElement("div");
    div.innerHTML = content;
    let base64Images = div.querySelectorAll("img"); // img 태그 추출
    
    let imgFiles = [];
    for(let i = 0; i<base64Images.length; i++) {
    	let src = base64Images[i].src;
        
        // base 64 image일 경우 javascript File 객체로 변환
        if(src.startsWith("data:")) {
            let arr = src.split(',');
            let mime = arr[0].match(/:(.*?);/)[1];
            let bstr = atob(arr[1]);
            let n = bstr.length;
            let u8arr = new Unit8Array(n);
            
            while(n--) {
            	u8arr[n] = bstr.charCodeAt(n);
            }
            
            let imgFile = new File([u8arr], "image", {type: mime});
            imgFiles.push(imgFile)
        }
    }
}

 

 

2. 변환된 imgFiles를 ajax로 전송하고 이미지 서버에 저장 후 생성된 url을 다시 받아 content의 img src 값을 변환한다.

let fdata = new FormData();
let index = 0;
imgFiles.forEach(e => {
	fdata.append("file"+index, imgFiles[index])
    index++;
})
fdata.append("length", imgFiles.length)

$.ajax({
	url: "/post/multiImageUploader.ajax"
    , data: fdata
    , method: "POST"
    , enctype: "multipart/form-data; charset=utf-8"
    , processData: false
    , contentType: false
    , cache: false
    , async: false
    , success: function(data) {
    	if(data.result == "0000") {
        	let resultFiles = data.imgFiles
            for(let i = 0; i<resultFiles.length; i++) {
            	content = content.replace(base64Images[i].src, resultFiles[i].sfileURL);
            }
        } else {
        	alert('이미지 업로드 실패')
        }
    }, error: function(data) {
    	alert('이미지 업로드 실패')
    }
})

return content;

 

 

 

 

 

 

 

 

728x90

댓글