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
http://iharder.sourceforge.net/current/java/base64/
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();
} */
%>
commons-codec-1.9-bin.zip