메뉴 건너뛰기

?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄 첨부
?

단축키

Prev이전 문서

Next다음 문서

크게 작게 위로 아래로 댓글로 가기 인쇄 첨부

Javascript 기술은 점점 발전하여 단순 JS만으로도 많은 기능을 사용할 수 있는데, 이번엔 화면을 캡처하는 방법을 알아보겠습니다.

 

요청사항 중 특정 요소를 캡처하여 이미지 데이터를 서버에 전송하고 저장을 원하였습니다.

화면 캡처 후 다운로드 기능은 사실 이미 많이 공유되고 있는데, 제가 겪었던 문제점에 대한 대응책이나 이런부분이 잘 보이질 않아 추가적으로 적어볼까합니다.

 

일단 html2canvas를 사용하여 동작시킬 예정이므로 해당 라이브러리를 추가합니다.

 

 

html2canvas를 통한 캡처 후 전송하기

<script src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>

아래는 공식사이트입니다.

https://html2canvas.hertzen.com/

 

이제 전송을 위해 ajax를 활용하여 전송 예제를 만들어보겠습니다.

-HTML

<section id="chart_box">
    <div class="chart">
     ...//차트에 해당하는 요소들
    </div>
</section>

 

 

-JS

$("#btn").on("click", function() {
	sreenShot($("#chart_box"));
});

function sreenShot(target) {
	if (target != null && target.length > 0) {
		var t = target[0];
		html2canvas(t).then(function(canvas) {
			var myImg = canvas.toDataURL("image/png");
			myImg = myImg.replace("data:image/png;base64,", "");

			$.ajax({
				type : "POST",
				data : {
					"imgSrc" : myImg
				},
				dataType : "text",
				url : contextPath + "/public/ImgSaveTest.do",
				success : function(data) {
					console.log(data);
				},
				error : function(a, b, c) {
					alert("error");
				}
			});
		});
	}
}

넣고 싶은 요소 $("#chart_box")를 매개변수로 집어넣고 0번째 데이터를 html2canvas 첫번째 파라미터에 처리합니다.

html2canvas는 Promise를 사용하는것으로 보이는데, 요소 처리가 완료되면 다음 이행동작을 정의합니다.

 

매개변수로 나온 canvas의 toDataURL을 통해 이미지 바이너리 데이터를 받을 수 있습니다.

거기서 앞에 붙는 데이터타입과 인코딩타입을 제거하고 서버로 전송하면 js부분은 끝입니다.

전송은 ajax를 통해 처리하였습니다.

 

 

-Server(java)

@ResponseBody
@RequestMapping(value = { "ImgSaveTest" }, method = RequestMethod.POST)
public ModelMap ImgSaveTest(@RequestParam HashMap<Object, Object> param, final HttpServletRequest request, final HttpServletResponse response) throws Exception {
	ModelMap map = new ModelMap();
	
	String binaryData = request.getParameter("imgSrc");
	FileOutputStream stream = null;
	try{
		System.out.println("binary file   "  + binaryData);
		if(binaryData == null || binaryData.trim().equals("")) {
		    throw new Exception();
		}
		binaryData = binaryData.replaceAll("data:image/png;base64,", "");
		byte[] file = Base64.decodeBase64(binaryData);
		String fileName=  UUID.randomUUID().toString();
		
		stream = new FileOutputStream("E:/test2/"+fileName+".png");
		stream.write(file);
		stream.close();
		System.out.println("캡처 저장");
	    
	}catch(Exception e){
		e.printStackTrace();
		System.out.println("에러 발생");
	}finally{
		if(stream != null) {
			stream.close();
		}
	}
	
	map.addAttribute("resultMap", "");
	return map;
}

파라미터로 넘긴 데이터를 문자열로 전달받고 바이너리 데이터를 스트림을 통해 읽어서 파일쓰기를 통해 파일을 남깁니다.

 

 

사용예시

html Page

 

 

전송버튼을 누르고 지정한 test2 디렉토리에 저장되는지 확인해보겠습니다.

 

 

 

 

정상적으로 파일이 써진 모습을 볼 수 있습니다.

 

 

개발시 주의사항

*아래 기재한 주의사항은 개인적으로 적용과 테스트를 해보면서 겪은 문제들입니다.

 

1. html2canvas에 넣는 첫번째 요소가 jQuery 선택자인 경우 id값일지라도 배열의 인덱스가 필요합니다.

ex) $("#test")[0]

 

2. 다운받으려는 특정요소는 width, height등 요소의 영역이 정확하게 지정되어 있어야합니다.

지정되지 않은 요소를 받게되면 브라우저상에서는 잘 보일지라도 전송된 데이터는 비어있거나 잘렸거나 등등 여러가지 문제가 발생할 수 있습니다.

 

3. 다운받으려는 특정요소의 위치가 position등을 통해 억지로 맞춰진 경우 정상출력이 되지 않을 수 있습니다.

 

4. div태그 내부의 img태그등 정보를 받아오는 데이터가 외부인 경우 정상적으로 출력되지 않습니다.

다른 예시 블로그 글들을 보면 http~를 통해 이미지를 가져오고 다운로드 받는다고 되어있는데, 막상 따라해보면 흰색 화면만 받아졌습니다. 서버 내부에 존재하는 이미지를 넣고 다운로드시 정상 출력되었습니다.

 

5. 인터셉터 관련 서버 코드 문제

저같은 경우는 XSS악성 스크립트 방지를 위해 서버코드로 넘어가는 모든 파라미터를 검사하는 로직을 추가해놨습니다.

html2canvas로 읽는 데이터가 얼마 안되는 경우에는 큰 문제가 없지만 복잡한 이미지를 만들게되면 그만큼 바이너리 데이터 또한 매우 커집니다. 캡처의 바이너리만 해도 문자열 길이가 약 7만5천개정도가 되었습니다. 여기서 로직을 체크하는 함수와 문자열이 겹치면서 서버로 전송이 안되는 이슈가 있어서, 해당 파라미터만 검사를 안하거나 url에 따라 예외처리등 약간의 극복(?)이 필요했습니다.

 

6. 바이너리 데이터를 넘기다보니 더욱 복잡한 이미지를 이미지화하여 전송하게되면 데이터는 더욱 커지게 되고 tomcat의 maxPortSize를 강제로 키우거나 -1처리를 통해 무제한으로 변경해야 할 수도 있습니다.

 

7. 높이가 body보다 큰 영역을 처리할 때 잘릴 수가 있습니다. 처리하는동안 body태그의 값을 제어하여 영역과 동일하게 또는 그 보다 크게 처리하였다가 원래 사이즈로 처리하는 로직이 필요합니다. - 20201126 추가


List of Articles
번호 제목 날짜 조회 수
247 'Array', 배열 및 다차원 배열 선언에 대해 알아보자! 2015.02.03 11110
246 'blur', 이미지 클릭시 테두리를 없애자! file 2015.02.03 7353
245 'button', 클릭한 횟수 알아내기! file 2015.02.03 10757
244 'checkbox', 체크박스 모두체크 그리고 모두해제! file 2015.02.03 7492
243 'focus', 엔터 누르고 이동하자! file 2015.02.03 12857
242 'onmouseover', 마우스 오버 효과 - 글씨 바꾸기! file 2015.02.03 9436
241 'open', 새창을 열어보자! file 2015.02.03 6036
240 'opener', 부모창과 자식창의 텍스트를 교환하자! file 2015.02.03 7308
239 'setInterval', 타이머를 사용하자! ==setTimeout 2015.02.03 6223
238 'setTimeout', 타이머를 사용하자! file 2015.02.03 7033
237 '레이블', 반복문을 제어하자! file 2015.02.03 5540
236 '문자 ↔ 숫자', 타입을 바꿔보자! 2015.02.03 6207
235 (소스)jqury 롤오버 버튼 쉽게 만들기 file 2014.03.01 5785
234 2단계 트리메뉴 마우스오버(mouseover), 온포커스(onfocus) 구현 2015.04.06 8204
233 3자리 마다 쉼표만 찍어주는 number_format 함수 2021.03.26 225
232 3자리마다 콤마찍기 2014.02.27 5755
231 5초 후에 해당페이지로 url 옮기기 2014.02.27 10485
230 5초후 자동으로 창닫기 2015.02.03 9034
229 == / === / != / !== 차이 2018.11.07 1443
228 ajax 사용시 Internal Sever Error 뜨는 경우 2021.03.26 960
Board Pagination Prev 1 2 3 4 5 6 7 8 9 10 ... 13 Next
/ 13

하단 정보를 입력할 수 있습니다

© k2s0o1d4e0s2i1g5n. All Rights Reserved