본문 바로가기

개발/Java & Spring

[Spring] Spring - Ajax 파일 전송, Javascript 이미지 미리보기

헬스일정웹페이지 개발 때는 Ajax 이용 안하고 View에 다 때려박았다면,

이번엔 Ajax로 파일 전송 및 업로드를 구현해보았다.


어려울 것 같아서 시도도 안해봤었는데 생각보다 할만했다.



우선 파일 업로드 폼을 작성한다.


	
<table>
<tbody><tr><td><input type="file" id="InputImage" onchange="readURL(this)"></td></tr>
		<tr><td><input type="text" placeholder="가로(pixel)" id="width"><input type="text" placeholder="세로(pixel)" id="height"></td></tr>
		<tr><td><input type="button" onclick="compression()" value="압축하기"></td></tr>
</tbody></table>


onchange="readURL(this)"  와 onclick="compression()" 이 핵심이다 


스크립트로 넘어가서 해당 메소드를 정의해준다.



먼저, 이미지 미리보기 소스 


function readURL(input) {
    	if (input.files && input.files[0]) {
        var reader = new FileReader();
        reader.readAsDataURL(input.files[0]);

    
        reader.onload = function (e) {
    
        	var tempImage=new Image();
        	tempImage.src=reader.result;
        	console.log(tempImage);
        	tempImage.onload=function(){
        		var canvas=document.createElement('canvas');
        		var canvasContext=canvas.getContext("2d");
        		
        		
            	var img = new Image();
	        	img.src = e.target.result;
	        	
	        	
        		canvas.width=img.width*0.5;
        		canvas.height=img.height*0.5;
        		
        		canvasContext.drawImage(this,0,0,canvas.width,canvas.height);
        		
        		var dataURI=canvas.toDataURL("image/png");
        		
        		document.querySelector("#thumbnail").src=dataURI;
   
        	}
        };
    
    	}
	}


file을 선택하면 onchange 함수가 작동되고 input 타입으로 해당 파일이 넘어온다. 


FileReader를 통해 해당 파일의 url을 읽어주고, 

onload - > 읽혀지게 되면 내부 함수가 실행되고 이미지로 변환하는 소스이다.


썸네일 출력이 목적이기 때문에 원본 이미지의 가로, 세로 비율을 0.5 배해서 출력해주었다. 


jpg 형식이면 var dataURI=canvas.toDataURL("image/png"); 를 변경시켜주도록 하는데, 이대로 두어도 출력은 잘 되더라. 


출력은 아래 따로 정의된  <img src="./resources/default_original.png" style="border: 2px dotted black" id="thumbnail"/> 여기에 된다. 





이제 Spring  과 파일을 주고받는 소스이다. 

form method="post" 를 이용할 수도 있겠지만, Ajax로 비동기 처리 해주었다 .



<< script 코드 >> 


function compression(){
		
		// initializing
		$('#img').attr('src', './resources/default.png')
		.width('50%')
  		.height('50%');
		
		
		var file=document.querySelector('#InputImage');
		
		var fileList=file.files;
		var reader=new FileReader();
		
		
		if(fileList && fileList[0]){
		reader.readAsDataURL(fileList[0]);
		  reader.onload = function (e) {
	        	var img = new Image();
	        	img.src = e.target.result;

	        	var formData = new FormData();
	        	formData.append('RequestParam',fileList[0]);

	            $.ajax( {
	                url:'/springpath',
	                type: 'POST',
	                data: formData,
	                processData: false,
	                contentType: false,
					dataType: 'json',//xml, json,  file을 받을 수 없음 
	                enctype: 'multipart/form-data',//매 우 중 요 
	                success: function(html){
	                	console.log('success');
	                },
	                error: function(error){

	                }
	            }).done(function( data ) {//server에서 데이터 반환된 뒤 실행되는 함수 
				$('#resultImg').attr('src', 'data:image/png;base64,'+data.resultBytes) //반환된 이미지(바이트스트림) 삽입
						.width($('#width').val()) 
	              		.height($('#height').val());
	            });
				
	        };
	      
		}
	}



나는 서버에서 PNG 이미지 압축을 해주었기 때문에 compress 어쩌고가 많지만, Ajax 형식만 참고하면 될 듯 하다.



다음 Java 코드 


@ResponseBody @RequestMapping(value="/springpath", method=RequestMethod.POST,produces="application/json;charset=UTF-8" ) public Map<String, String> compactionImage(@RequestParam("ori") CommonsMultipartFile file) throws IOException { Map<String, String> result; if(file.getContentType().equals("image/jpeg") || file.getContentType().equals("image/jpg")) result=compactService.getCompactedJPGImage(file); else result=compactService.getCompactedPNGImage(file); return result; }


서비스 함수는 일단 회사에서 사용하는거라 올리기 좀 그래서 생략한다.

Pngtastic API를 활용했다는 것만 언급해두겠다.




 


중요한건,

produces="application/json;charset=UTF-8" 

와 Map으로 Json 객체로 변환 후 리턴해 주었다는 것. (jackson core, json-simple maven 의존 추가는 필수다)


@RequestParam("ori") CommonsMultipartFile file


Parameter 명과 타입을 반드시 이렇게 해주어야한다.

MultipartFile로  받으면 계속 에러가난다. 여기서 삽질 하루했다 정말 ㅠㅠㅠ 자동 변환이 안되는 것 같다. 



여기서 Param 명은 위 스크립트 코드의

	formData.append('ori',fileList[0]);


과 일치시키는 것이다. 


fromData도 잘 변환해주어야한다. 





서비스 코드 전부를 공개하진 못하지만, 파일은 바이트url로 변경하는 것은


result.put("resultBytes", Base64.getEncoder().encodeToString(Files.readAllBytes(compressed_file.toPath())));


여기 Base64 클래스를 활용하면 된다. 





그동안 Javascript 기초가 탄탄하지 않아 넘겼던 Ajax를 드디어 써보았다.

왜 그렇게 쫄았나 싶기도 하고.. 역시 사람은 닥치면 다 하게되는구나 싶기도 하고 ㅋㅋㅋㅋㅋㅋ