메뉴 건너뛰기

?

단축키

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
번호 제목 날짜 조회 수
207 금액에 점찍고 한글 표시하기 2019.01.16 1271
206 체크박스 전체 선택 및 해제, 반드시 1개 이상 선택 강제 2019.01.16 1308
205 div태그를 이용한 클릭시 레이어 띄우기 2019.01.16 1328
204 오늘 날짜 구하기 2018.11.07 1416
203 opener 값전달, 함수실행.(자식창에서 부모창으로 값전달, 함수실행) 2021.03.26 1438
202 == / === / != / !== 차이 2018.11.07 1443
201 span - 동적으로 글자 바꾸기, 보이기 안보이기 2019.01.16 1448
200 엔터키 / enter key submit form 2018.09.28 1528
199 날짜 계산 (Date) 마지막 날짜(말일)/윤달/윤년 처리하기 2021.08.20 1542
198 특정 부분 인쇄 자바스크립트 2019.01.16 1588
197 cross site scripting을 막기위한...javascript 2018.07.24 1596
196 key pressing 누르거나 클릭중인 이벤트 예제 2018.08.29 1622
195 시간 계산하기 (시/분/초/ 더하기, 빼기) 2021.08.20 1708
194 jQuery 엘리먼트 선택 2018.10.27 1732
193 팝업창 차단 "허용 메시지" 2018.09.28 1738
192 문자열 안에 쌍따옴표, 홑따옴표 표시하는 3가지 방법 file 2021.08.20 1792
191 반복문 사용할때 태그 식별하기 data-item 2018.07.04 1849
190 자바스크립트 urlencode(), urldecode(), rawurlencode(), rawurldecode() 2018.10.27 1913
189 텍스트박스 입력제한(숫자,영문,한글,특수기호) 2019.01.16 1992
» Javascript - 화면 캡처 후 서버에 저장하기(html2canvas 사용법, 주의사항) file 2021.03.09 2176
Board Pagination Prev 1 2 3 4 5 6 7 8 9 10 ... 13 Next
/ 13

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

© k2s0o1d4e0s2i1g5n. All Rights Reserved