romworld

Spring 15 - 파일 다운로드 , Ajax 연습 본문

Spring

Spring 15 - 파일 다운로드 , Ajax 연습

inderrom 2023. 2. 2. 12:18
1. 파일 다운로드 구현
2. Ajax를 사용하여 파일업로드 하기

 


controller 패키지에 PracticeController, practice 폴더에 jsp 파일을 만든다.

 

Ajax 연습

 

Controller응답
1. void
2. spring
3. 자바빈즈 클래스
4. 컬렉션 List 타입
5. 컬렉션 Map 타입

6. ResponseEntity<void>
7. ResponseEntity<spring>
8. ResponseEntity<자바빈즈 클래스>
9. ResponseEntity<컬렉션 List 타입>
10. ResponseEntity<컬렉션 Map 타입> -
-> 데이터 뿐만 아니라 header와 응답 상태까지 설정하고 나타낸다
--> 최프 때 사실상 사용 안한다

1. void일 경우 리턴 생략 @GetMapping("/lprod/list") public void 메소드명()
--> lprod 폴더 list.jsp 리턴
2. string일 경우 public String 메소드명(){ return "lprod/list" }
3. 자바빈즈(List, Map)
 - Model model.addAttribute("이름", 데이터)
   return "lprod/list" forword 방식으로 데이터를 보냄

 - ResponseBody
   return 데이터
    responseBody는 전부 JSON으로 보낸다.
    비동기 방식으로 보냄(ajax)

==> 가장 많이 사용하는 건 String 방식이다.

 

 

 

<PracticeController.java>

package kr.or.ddit.controller;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.common.net.HttpHeaders;

import kr.or.ddit.vo.LprodVO;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
public class PracticeController {

	// 연습 1

	// 요청 URI : /practice/ajaxHome
	@GetMapping("/practice/ajaxHome")
	public String ajaxHome() {
		// forwarding
		return "practice/ajaxHome";

	}

	/*
	 * 경로 패턴 매핑 요청 경로를 동적으로 표현이 가능한 경로 패턴으로 지정할 수 있음 - URI 경로 상의 변하는 값을 경로
	 * 변수(PathVariable)로 취급함 - 경로 변수에 해당하는 값을 파라미터 변수(매개변수-파라미터를 받아 값을 저장하는 변수)에 설정할
	 * 수 있음
	 */
	// 요청URI : /board/100 => 100은 boardNo(게시판 기본키)
	// 요청방식 : get
	// {boardNo} = 100
	@PostMapping("/board/{boardNo}")
	public ResponseEntity<String> read(@PathVariable("boardNo") int boardNo) {
		log.info("boardNo : " + boardNo);

		// String을 응답
		ResponseEntity<String> entity = new ResponseEntity<String>("SUCCESS", HttpStatus.OK);

		return entity;
	}
	// 연습 2

	// 요청URI : /board/goHome0301
	// JSON 데이터를 받을 땐.. @RequestBody
	// JSON 데이터로 응답할 땐.. @ResponseBody
	@ResponseBody
	@GetMapping("/board/goHome0301")
	public LprodVO home0301() {
		log.info("home0301에 왔다");

		LprodVO lprodVO = new LprodVO();
		lprodVO.setLprodId(1);
		lprodVO.setLprodGu("P101");
		lprodVO.setLprodNm("컴퓨터제품");

		// forwarding도 아니고 redirect도 아님
		// 자바빈 객체가 JSON으로 보내짐
		return lprodVO;

	}

	// 연습 3

	// 요청 URI : /board/goHome04"
	// 요청파라미터 : {"lprodId":lprodId,"lprodGu":lprodGu,"lprodNm":lprodNm}
	// 방식 : post
	// 리턴타입 : json
	@ResponseBody
	@PostMapping("/board/goHome04")
	public List<LprodVO> goHome04(@RequestBody LprodVO lprodVO) {
		log.info("lprodVO : " + lprodVO);

		List<LprodVO> lprodVOList = new ArrayList<LprodVO>();

		LprodVO vo1 = new LprodVO();
		vo1.setLprodId(2);
		vo1.setLprodGu("P102");
		vo1.setLprodNm("전자제품");

		lprodVOList.add(vo1);

		vo1 = new LprodVO();
		vo1.setLprodId(3);
		vo1.setLprodGu("P103");
		vo1.setLprodNm("피혁잡화");

		lprodVOList.add(vo1);

		vo1 = new LprodVO();
		vo1.setLprodId(4);
		vo1.setLprodGu("P104");
		vo1.setLprodNm("문구류");

		lprodVOList.add(vo1);

		log.info("lprodVOList : " + lprodVOList);

		return lprodVOList;
	}
	
	// 요청 URI : /board/goHome05
	// 방식 : post
	// 컬렉션 Map 타입을 JSON으로 응답
	@ResponseBody
	@PostMapping("/board/goHome05")
	public Map<String, LprodVO> goHome05(){
		log.info("goHome05에 왔다");
		
		Map<String,LprodVO> map = new HashMap<String, LprodVO>();
		
		LprodVO vo1 = new LprodVO();
		vo1.setLprodId(2);
		vo1.setLprodGu("P102");
		vo1.setLprodNm("전자제품");
		
		map.put("Key1", vo1);
		
		vo1 = new LprodVO();
		vo1.setLprodId(3);
		vo1.setLprodGu("P103");
		vo1.setLprodNm("피혁잡화");
		
		map.put("Key2", vo1);

		vo1 = new LprodVO();
		vo1.setLprodId(4);
		vo1.setLprodGu("P104");
		vo1.setLprodNm("문구류");
		
		map.put("Key3", vo1);
		
		log.info("map : " + map);
		
		return map;
	}

}

 

 

<ajaxHome.jsp>

<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/resources/js/jquery.3.6.0.js"></script>
<title>도서관리시스템</title>
<script type="text/javascript">
	$(function() {
		// 아이디가 btnSubmit인 버튼을 클릭 시
		//1) 아이디가 boardNo인 요소의 값을 boardNoVal 변수에 할당
		//2) ajax 구문을 작성.(url(/board/+boardNoVal), contentType(application/json;charset=utf-8),
		//data, type(get), success) 
		//3) data는 json데이터.{boardNo:boardNoVal}
		$("#btnSubmit").on("click", function() {
			let boardNoVal = $("#boardNo").val();
			let data = {
				"boardNo" : boardNoVal
			};

			//url : 요청경로
			//contentType : 보내는 데이터 타입
			//dataType : 응답 데이터타입
			//data : 요청 시 전송할 데이터
			//type : get, post, put
			//요청URI : /board/100
			$.ajax({
				url : "/board/" + boardNoVal,
				contentType : "application/json;charset=utf-8",
				data : JSON.stringify(data),
				type : "post",
				success : function(result) {
					//ResponseEntity<String> entity = 
					//new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
					//result : SUCCESS
					console.log("result : " + result);
				}
			});
		});

		// goHome0301버튼을 클릭 시
		// ajax로 board/goHome0301 URI를 요청(방식: get)
		// success로 lprodVO 자바빈 객체 데이터를  result 오브젝트 변수에 담자
		//dataType:"json" 생략가능

		$("#goHome0301").on(
				"click",
				function() {
					$.ajax({
						url : "/board/goHome0301",
						type : "get",
						dataType : "json",
						success : function(result) {
							console.log("result : " + JSON.stringify(result));

							let lprodId = result.lprodId;
							let lprodGu = result.lprodGu;
							let lprodNm = result.lprodNm;
							console.log("lprodId : " + lprodId + "lprodGu : "
									+ lprodGu + "lprodNm : " + lprodNm);

							$("input[name=lprodId]").val(lprodId);
							$("input[name=lprodGu]").val(lprodGu);
							$("input[name=lprodNm]").val(lprodNm);

						}
					});
				});

		//goHome04
		$("#goHome04").on(
				"click",
				function() {
					//1) name이 lprodId, lprodGu, lprodNm인 요소의 value를 각각의 이름의 변수에 담은 후
					// data 오브젝트 변수에 json 데이터로써 저장해보자
					//2) 요청URI는 /board/goHome04
					//3) JSON.stringify(data)를 데이터로 담아 요청해보자
					//4) type은 post
					//5) success는 result변수로 콜백해보자

					let lprodId = $("input[name=lprodId]").val();
					let lprodGu = $("input[name=lprodGu]").val();
					let lprodNm = $("input[name=lprodNm]").val();

					let data = {
						"lprodId" : lprodId,
						"lprodGu" : lprodGu,
						"lprodNm" : lprodNm
					};

					$.ajax({
						url : "/board/goHome04",
						contentType : "application/json;charset=utf-8",
						data : JSON.stringify(data),
						dataType : "json",
						type : "post",
						success : function(result) {
							console.log("result : " + JSON.stringify(result));
							
							let str = "";
							
							// list 데이터 처리
							// result(json데이터) : List<LprodVO>
							// item : LprodVO{"lprod"}
							$.each(result, function(index, item) {
								let v_Id = item.lprodId;
								let v_Gu = item.lprodGu;
								let v_Nm = item.lprodNm;

								console.log("v_Id : " + v_Id + ", v_Gu : "
										+ v_Gu + ", v_Nm : " + v_Nm);
								
								str += "<p><input type='text' name='lprodVOList["+index+"].lprodId' value='" + v_Id + "' />";
								str += "<input type='text' name='lprodVOList["+index+"].lprodGu' value='" + v_Gu + "' />";
								str += "<input type='text' name='lprodVOList["+index+"].lprodNm' value='" + v_Nm + "' /></p>";

								//아이디가 divLprod인 div요소 내부에 목록을 채우자
								/* ex)
								<div id="divLprod">
									<p><input type="text" name="lprodVOList[0].lprodId" value="2" />
									<input type="text" name="lprodVOList[0].lprodGu" value="P102" />
									<input type="text" name="lprodVOList[0].lprodNm" value="전자제품" /></p>
									<p><input type="text" name="lprodVOList[1].lprodId" value="3" />
									<input type="text" name="lprodVOList[1].lprodGu" value="P103" />
									<input type="text" name="lprodVOList[1].lprodNm" value="피혁잡화" /></p>
									<p><input type="text" name="lprodVOList[2].lprodId" value="4" />
									<input type="text" name="lprodVOList[2].lprodGu" value="P104" />
									<input type="text" name="lprodVOList[2].lprodNm" value="문구류" /></p>
								</div>
								 */

							});
							console.log("str : " + str)
							$("#divLprod").append(str);
						}
					});
				});

		//map->json 데이터 받기
		$("#goHome05").on("click", function() {
			$.ajax({
				url : "/board/goHome05",
				type : "post",
				dataType : "json",
				success : function(result) {	
					console.log("result : " + JSON.stringify(result));
					
					let str = "";
					
					$.each(result,function(index,item){
						let v_Id = item.lprodId;
						let v_Gu = item.lprodGu;
						let v_Nm = item.lprodNm;
						
						console.log("v_Id : " + v_Id + ", v_Gu : "
								+ v_Gu + ", v_Nm : " + v_Nm);
						
						 
					});
				}
			});
		});
	});
</script>
</head>
<body>
	<!-- 연습 1 -->
	<form>
		<p>
			<input type="text" name="boardNo" id="boardNo" />
		</p>
		<p>
			<input type="button" id="btnSubmit" value="전송" />
		</p>
	</form>

	<!-- 연습 2 -->
	<form>
		<p>
			<input type="text" name="lprodId" readonly />
		</p>
		<p>
			<input type="text" name="lprodGu" readonly />
		</p>
		<p>
			<input type="text" name="lprodNm" readonly />
		</p>
		<p>
			<input type="button" id="goHome0301" value="goHome0301" />
		</p>
	</form>

	<!-- 연습 3 -->
	<form>
		<p>
			<input type="button" id="goHome04" value="goHome04" />
		</p>
	</form>

	<!-- 연습 4 -->
	<form>
		<div id="divLprod"></div>
		<p>
			<input type="button" id="goHome05" value="goHome05" />
		</p>
	</form>
</body>
</html>

 

 

연습 1

console로 찍힘

연습 2

 

연습 3

 

연습 4

 


파일 다운로드 연습

  • 컨트롤러와 jsp 전부 ajax연습과 같은 파일에서 이어서 연습한다.

< PracticeController.java>

	// 파일 다운로드 연습
	//SpringFramework를 이용한 파일 다운로드
		/* MIME(Multipurpose Internet Mail Extensions)
		 문자열을 전송할 때는 7비트 아스키파일로 전송하여 사용하지만
		 사진, 음악, 동영상, 문서 파일을 보낼 땐 8비트 데이터(바이너리 데이터)를 사용함.
		 이것을 전송하기 위해서는 바이너리 데이터를 텍스트로 변환하는 인코딩작업이 필요함.
		 
		 MIME은 이런 인코딩 방식의 일종. 인코딩 + data type(contents type)
		 
		 image/jpeg
		 */
		//요청URI : /board/goHome1102
		@ResponseBody
		@GetMapping("/board/goHome1102")
		public ResponseEntity<byte[]> home1102() throws IOException{
			log.info("home1102에 왔다");
			//입력 스트림(00110111011000..)
			InputStream in = null;
			ResponseEntity<byte[]> entity = null;
			
			HttpHeaders headers = new HttpHeaders();
			
			String fileName = "C:\\eclipse_202006\\workspace\\springProj\\src\\main\\webapp\\resources\\upload\\2023\\01\\31\\0d1564bb-445a-4e7b-b432-4585c7d94d5f_KakaoTalk_20230127_145604043.jpg";			
			
			try {
				in = new FileInputStream(fileName);
				//APPLICATION_OCTET(8비트)_STREAM(순수한 바이너리 데이터) : 
				//	표준으로 정의되어 있지 않은 파일인 경우 지정하는 타입
				headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
				//Content-Disposition : 웹브라우저에서 다운로드 창의 띄움
				//	이 뒤에는 파일 이름과 확장자를 지정해야 함
				// 스트림 파일을 통해 write해줌
				headers.add("Content-Disposition", "attachment;filename=\"" + 
							new String(fileName.getBytes("UTF-8"),"ISO-8859-1") + "\"");
				//new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
				entity = new ResponseEntity<byte[]>(IOUtils.toByteArray(in),
						headers, HttpStatus.CREATED);		
			} catch (FileNotFoundException e) {
				log.info(e.getMessage());
				entity = new ResponseEntity<byte[]>(HttpStatus.BAD_REQUEST);
			}finally {
				in.close();
			}
			return entity;
		}

매핑한 url를 입력하면 파일이 다운로드 받아진다.

 

 


Ajax로 파일 업로드 연습

 

<PracticeController.java>

 요청 URI : /board/uploadAjax
		 요청 데이터:
				  <form>
					 <input type="file" name="uploadFile" />
					 <input type="file" name="uploadFile" />
					 <input type="file" name="uploadFile" />
					 <input type="file" name="lprodId" value="1" />
					 <input type="file" name="lprodGu" value="P101" />
					 <input type="file" name="lprodNm" value="컴퓨터제품" />
				  <form> 
		 방식 : post
		 요청 파라미터 : {lprodId=1,lprodGu=P101,lprodNm=컴퓨터제품,uploadFile=파일객체}
		 */
		@ResponseBody
		@PostMapping("/board/uploadAjax")
		public ResponseEntity<String> uploadAjax (String lprodId, String lprodGu,
				String lprodNm, MultipartFile[] uploadFile,
				@RequestParam Map<String, Object> map,
				@ModelAttribute LprodVO lprodVO
				){
			log.info("lprodId : " + lprodId + ", lprodGu : " + lprodGu +",lprodNm : " + lprodNm);
			
			log.info("map : " + map);
			log.info("lprodVO : " + lprodVO);
			
			return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
		}

 

<ajaxHome.jsp>

  • 폼태그 추가
<!-- ajax 파일업로드 연습 -->
	<form>
		<p>
			<input type="file" id="uploadFile" name="uploadFile" multiple />
		</p>
		<p>
			<input type="button" id="btnUpload" value="ajax파일업로드" />
		</p>
	</form>
  • 스크립트 추가
	// ajax파일업로드 처리
		// e : 클릭 이벤트
		$("#btnUpload").on("click", function(){
			// 가상의 form 태그 생성. <form></form>
			let formData = new FormData();
			// <input type="file" id="uploadFile" name="uploadFile" multiple />
			let inputfile = $("input[name='uploadFile']");
			// 파일 오브젝트 안에 이미지 파일들을 가져와보자
			// .files : 파일 오브젝트 안에 들어있는 이미지들
			let files = inputfile[0].files;
			//files : [object fileList]
			console.log("files : " + files);
			
			
			// 가상의 form인 formData Object에 filedata를 추가해보자
			for(let i=0; i < files.length; i++){
				// 파일 확장자/크기 체킹(확장자가 exe, sh, zip, alz이면 안됨)
				if(!checkExtension(files[i].name, files[i].size)){
					// 반복문 종류 및 함수 종료
					return false;
				}
				
				// <form>
				// <input type="file" name="uploadFile" />
				// <input type="file" name="uploadFile" />
				// <input type="file" name="uploadFile" />
				// <form> 
				// form 안에 누적이 되어야 하므로 append를 써준다.
				formData.append("uploadFile",files[i]);
			}
			
			// 만약 value를 문자열로 넣는 경우에는 이런 식으로 넣어주면 된다.
			
			// <form>
			// <input type="file" name="uploadFile" />
			// <input type="file" name="uploadFile" />
			// <input type="file" name="uploadFile" />
			// <input type="file" name="lprodId" value="1" />
			// <input type="file" name="lprodGu" value="P101" />
			// <input type="file" name="lprodNm" value="컴퓨터제품" />
			// <form> 
			formData.append("lprodId","1")
			formData.append("lprodGu","P101")
			formData.append("lprodNm","컴퓨터제품")
			
			console.log("formData :" + formData);
			
			// contentType : 보내는 데이터 타입
			// dataType : 응답 데이터 타입
			//processData : 데이터 파라미터를 data라는 속성으로 넣는데, 제이쿼리 내부적으로 쿼리스트링을 구성합니다.
			// 				파일 전송의 경우 쿼리스트링을 사용하지 않으므로 해당 설정을 false로 비활성화합니다.
			//contentType : Content-Type을 설정 시, 사용하는데 해당 설정의 기본값은 
			//				"application/x-www-form-urlencoded; charset=utf-8"입니다.
			//				하여, 기본값으로 나가지 않고 "multipart/form-data; 로 나갈수 있도록 설정을 false 합니다.
			//				request 요청에서 Content-Type을 확인해보면 
			//				"multipart/form-data; boundary=----WebKitFormBoundary~~~~"와 같은 값으로
			//				전송된 것을 확인 할 수 있습니다.
				
			
			$.ajax({
				url:"/board/uploadAjax",
				processData:false,
				contentType:false,
				data:formData,
				dataType:"json",
				type:"post",
				success:function(result){
					console.log("result : " +JSON.stringify(result));
				}
			});
		});
		// 이미지 체킹
		//(.*?) : 파일명
		// * : 0 이상   ? : 있어도 되고 없어도 되고..
		// | : 또는
		// \. : 이스케이프로 처리하여 문자 . 을 의미
		let regex = new RegExp("(.*?)\.(exe|sh|zip|alz)$"); // 정규식
		let maxSize = 5242880; // 5MB
		
		function checkExtension(filename, fileSize){//확장자, 크기 체킹
			//1) 문제 발생 : false 리턴
			if(fileSize >= maxSize){
				alert("파일 사이즈가 초과되었습니다.");
				// 함수 종료
				return false;
			}
			// filename : 새롬이.zip
			if(regex.test(filename)){
				alert("해당 종류의 파일은 업로드할 수 없습니다.");
				return falsee;
			}
			//2) 통과 : true 리턴
			return true;
		}
Comments