본문 바로가기

HTML5/Canvas Upload

HTML5 Canvas Image Upload example

HTML5 캔바스 상의 이미지를 서버로 업로드하는 예



웹브라우저의 Canvas 에 그려진 이미지를 웹서버로 전달하여 이미지 파일로 저장하려고 한다.

canvas.toDataURL() 함수를 이용하여 Base64 문자열로 인코딩된 이미지 데이터를 구할 수 있으므로 일반 문자열처럼 쉽게 서버로 전송할 수 있다.

이미지 데이터가 Base64 문자열로 인코딩되면 문자열의 첫 부분은 'https://t1.daumcdn.net/cfile/tistory/221EF94756E6601616"txc-textbox" style="border: 1px solid rgb(203, 203, 203); padding: 10px; background-color: rgb(255, 255, 255);">

java.util.Base64


org.apache.commons.codec.binary.Base64  

commons-codec-1.9-bin.zip

           

http://iharder.sourceforge.net/current/java/base64/          

Base64-v2.3.7.zip                



Canvas에 그려진 이미지를 Base64 문자열로 인코딩하여 jQuery.ajax() 를 이용하여 서버로 전송하는 클라이언트측 코드

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Image Capture and Submit</title>
<script type="text/javascript" src="jquery-2.1.1.min.js"></script>
<script type="text/javascript">

var imageObj = null;  
var mx,my,cmx,cmy = 0;
var isDown = false;

$(function() {
    $('#file-input').change(function(e) {
        var file = e.target.files[0],
            imageType = /image.*/;

        if (!file.type.match(imageType))
            return;

        var reader = new FileReader();
        reader.onload = fileOnload;
        reader.readAsDataURL(file);        
    });

  
    function fileOnload(e) {
        var $img = $('<img>', { src: e.target.result });
        var canvas1 = $('#canvas1')[0];
        var context = canvas1.getContext('2d');

        $img.load(function() {
            context.drawImage(this, 0, 0);
            imageObj = this;
        });
    }
    
    $('#canvas1').on('mousedown',function(e){
    	var element = this;
    	var offsetX = 0;
    	var offsetY = 0;
  	    if (element.offsetParent !== undefined) {
  	        do {
  	          offsetX += element.offsetLeft;
  	          offsetY += element.offsetTop;
  	        } while ((element = element.offsetParent));
  	        mx = e.pageX - offsetX;
  	        my = e.pageY - offsetY;
  	        isDown = true;
  	        console.log(mx+','+my);
  	    }
    });
    
	$('#canvas1').on('mousemove',function(e){
		if(!isDown) return;
		var element = this;
    	var offsetX = 0;
    	var offsetY = 0;
  	    if (element.offsetParent !== undefined) {
  	        do {
  	          offsetX += element.offsetLeft;
  	          offsetY += element.offsetTop;
  	        } while ((element = element.offsetParent));
  	        cmx = e.pageX - offsetX;
  	        cmy = e.pageY - offsetY;
  	      	
  	        console.log(cmx+','+cmy);
  	        
  	      var canvas1 = $('#canvas1')[0];
          var context = canvas1.getContext('2d');
          context.drawImage(imageObj,0,0);//배경 이미지를 그린다
          
          //마우스로 선택된 영역에 대시라인으로 사각형을 그린다
          context.setLineDash([5]);
          context.strokeStyle = 'red';
          context.strokeRect(mx,my,cmx-mx,cmy-my);
  	    }
    });
	
	$('#canvas1').on('mouseup',function(e){
		var canvas1 = $('#canvas1')[0];
        var context = canvas1.getContext('2d');
        context.drawImage(imageObj,0,0);//배경 이미지를 그린다
        
        //마우스로 선택된 영역에 반투명 사각형을 그려서 선택영역을 표시해준다
        context.fillStyle = 'rgba(30,0,0,0.1)';
        context.fillRect(mx,my,cmx-mx,cmy-my);
        
        //마우스로 선택된 영역에 대시라인으로 사각형을 그린다
        context.setLineDash([5]);
        context.strokeStyle = 'red';
        context.strokeRect(mx,my,cmx-mx,cmy-my);
		isDown = false;
    });
	
    $('#save').click(function(){
    	sendBase64Img();
    });
    
    $('#copy').click(function() {
    	drawOnCanvas2();
    });
});

function drawOnCanvas2() {
	var canvas2 = $('#canvas2')[0];
	
	$(canvas2).attr('width', cmx-mx+'px');
	$(canvas2).attr('height', cmy-my+'px');
	
    var context = canvas2.getContext('2d');
    context.clearRect(0,0,canvas2.width, canvas2.height);
    
    var sx = mx;
    var sy = my;
    var sw = cmx-mx;
    var sh = cmy-my;
    var dx = 0;
    var dy = 0;
    var dw = sw;
    var dh = sh;

    context.drawImage(imageObj, sx, sy, sw, sh, dx, dy, dw, dh);
}

function sendBase64Img() {
	var canvas2 = document.getElementById('canvas2');
	var dataURL = canvas2.toDataURL();//이미지 데이터가 base64 문자열로 인코딩된 데이터
	// base64문자열의 첫 부분에 위치한 'https://t1.daumcdn.net/cfile/tistory/24343B4956E6601629"");*/
	$.ajax({
	  type: "POST",
	  url: "saveBase64.jsp",
	  contentType: "application/x-www-form-urlencoded; charset=utf-8",
	  data: { "imgBase64": dataURL }
	}).success(function(o) {
	  alert('선택영역을 서버의 이미지 파일에 저장했습니다'); 
	});
}
</script>
</head>
<body>
<canvas id="canvas1" width="500px" height="300px"></canvas>
<br>
<input type="file" id="file-input">
<button id="copy">Copy Selection</button>
<button id="save">Save to Server</button>
<p>
<canvas id="canvas2" width="500px" height="300px"></canvas>
</body>
</html>




서버측 코드 (jsp), Base64 인코딩 문자열을 수신하여 원래의 이미지 데이터로 디코딩하여 이미지 파일에 저장한다

<%@page import="test.base64.Base64"%>
<%--@page import="org.apache.commons.codec.binary.Base64"--%>
<%@page import="java.io.*"%>
<%@page import="java.awt.image.*"%>
<%@page import="javax.imageio.*"%>
<%--@page import="java.util.Base64"--%>
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%
	request.setCharacterEncoding("utf-8");
	String base64Str = request.getParameter("imgBase64");
	
	//인코딩된 문자열의 처음에 위치한 'https://t1.daumcdn.net/cfile/tistory/2159EF4856E6601716",")+1, base64Str.length());
	
	/* sourceforge에서 배포하는 Base64 클래스를 사용하면 가장 간단하게 디코딩과 이미지 파일에 저장을 동시에 처리한다*/
	Base64.decodeToFile(base64Str, "d:/test/decodedImg.png"); //jpg,png ok

	
	/* java.util.Base64 클래스를 사용하여 디코딩한 후에 ImageIO를 이용하여 이미지 파일에 저장한다
	byte[] decodedBytes = Base64.getDecoder().decode(base64Str); //java.util.Base64
	try {
            BufferedImage bm = ImageIO.read(new ByteArrayInputStream(decodedBytes));
       	    ImageIO.write(bm, "png", new File("d:/test/decodedImg.png"));
    	} catch (IOException e) {
        	e.printStackTrace();
    	} */
	
	
	/* Apache Base64 클래스를 이용하여 디코딩한 후에 ImageIO를 이용하여 이미지 파일에 저장한다
	byte[] decodedBytes = Base64.decodeBase64(base64Str); //apache Base64
	try {
            BufferedImage bm = ImageIO.read(new ByteArrayInputStream(decodedBytes));
            ImageIO.write(bm, "png", new File("d:/test/decodedImg.png"));
    	} catch (IOException e) {
        	e.printStackTrace();
    	} */
%>