Controller

FileUploadController.java

package kr.or.ddit.controller.file.item01;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

import javax.annotation.Resource;
import javax.inject.Inject;

import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;

import kr.or.ddit.controller.file.item01.service.ItemService;
import kr.or.ddit.vo.Item;
import lombok.extern.slf4j.Slf4j;

@Controller
@RequestMapping("/item")
@Slf4j
public class FileUploadController01 {
/*
 * 13장 파일업로드
 * 
 * 1. 파일업로드 설명
 * 
 * 	- 파일 업로드 등록 기능 컨트롤러 메소드 만들기 (itemRegister:post)
 * 	- 파일 업로드 등록 기능 서비스 인터페이스 메소드 만들기
 * 	- 파일 업로드 등록 기능 서비스 클래스 메소드 만들기
 * 	- 파일 업로드 등록 기능 Mapper 인터페이스 메소드 만들기
 * 	- 파일 업로드 등록 기능 Mapper xml 쿼리 만들기
 * 	- 파일 업로드 등록 완료 페이지 만들기.
 *  - 여기까지 확인 
 *  
 * 	- 파일 업로드 목록 화면 컨트롤러 메소드 만들기 (itemList:post)
 * 	- 파일 업로드 목록 화면 서비스 인터페이스 메소드 만들기
 * 	- 파일 업로드 목록 화면 서비스 클래스 메소드 만들기
 * 	- 파일 업로드 목록 화면 Mapper 인터페이스 메소드 만들기
 * 	- 파일 업로드 목록 화면 Mapper xml 쿼리 만들기
 * 	- 파일 업로드 목록 화면  만들기(item/list).
 *  - 여기까지 확인 
 *  
 * 	- 파일 업로드 수정 화면 컨트롤러 메소드 만들기 (itemModifyForm:post)
 * 	- 파일 업로드 수정 화면 서비스 인터페이스 메소드 만들기
 * 	- 파일 업로드 수정 화면 서비스 클래스 메소드 만들기
 * 	- 파일 업로드 수정 화면 Mapper 인터페이스 메소드 만들기
 * 	- 파일 업로드 수정 화면 Mapper xml 쿼리 만들기
 * 	- 파일 업로드 수정 화면  만들기(item/modify.jsp).
 *  - 파일 업로드 수정 기능 컨트롤러 메소드 만들기 (itemModify:post)
 * 	- 파일 업로드 수정 기능 서비스 인터페이스 메소드 만들기
 * 	- 파일 업로드 수정 기능 서비스 클래스 메소드 만들기
 * 	- 파일 업로드 수정 기능 Mapper 인터페이스 메소드 만들기
 * 	- 파일 업로드 수정 기능 Mapper xml 쿼리 만들기
 *  - 여기까지 확인 
 */
	
	// root-context.xml 에서 설정한 uploadPath 빈등록 path 경로를 사용한다.(value로 설정했던 값)
	@Resource(name="uploadPath")
	private String resourcesPath;
//	private String uploadPath = "C://upload";
	
	@Inject
	private ItemService itemService;
	
	// 등록 페이지로 가는 메소드
	@RequestMapping(value="/register", method = RequestMethod.GET)
	public String itemRegisterForm() {
		return "item/register";
	}
	
	// 파일 등록을 진행하는 메소드
	@RequestMapping(value="/register", method = RequestMethod.POST)
	public String itemRegister(Item item, Model model) throws IOException {
		MultipartFile file = item.getPicture();
		
		log.info("originalName : " + file.getOriginalFilename());
		log.info("size : " + file.getSize());
		log.info("contentType : " + file.getContentType());
		
		// 넘겨받은 파일을 이용하여 파일 업로드(복사)를 진행한다.
		// return : UUID + "_" _ 원본 파일명
		String createdFileName = uploadFile(file.getOriginalFilename(), file.getBytes());
		item.setPictureUrl(createdFileName);
		itemService.register(item);
		model.addAttribute("msg", "등록이 완료되었습니다");
		return "item/success";
	}
	
****	// 업로드할 파일 생성
	private String uploadFile(String originalName, byte[] fileData) throws IOException {
		System.out.println("resourcesPath : " + resourcesPath);
		UUID uuid = UUID.randomUUID(); // UUID 파일명 생성 준비
		String createdFileName = uuid.toString() + "_" + originalName; //UUID + "_" + 원본파일명
		
		File file = new File(resourcesPath);
		if(!file.exists()) {
			file.mkdirs();
		}
		
		File target = new File(resourcesPath, createdFileName);
		FileCopyUtils.copy(fileData, target); // 파일 복사
		return createdFileName;
	}
	
	// 파일 목록 화면 이동 메소드
	@RequestMapping(value="/list", method = RequestMethod.GET)
	public String itemList(Model model) {
		List<Item> itemList = itemService.list();
		model.addAttribute("itemList", itemList);
		return "item/list";
	}
	
	**// 수정 폼으로 이동**
	@RequestMapping(value="/modify", method = RequestMethod.GET)
	public String itemModifyForm(int itemId, Model model) {
		Item item = itemService.read(itemId);
		model.addAttribute("item", item);
		return "item/modify";
	}
	
	**// 파일 미리보기를 위한 메소드**
	@RequestMapping(value="/display")
	public ResponseEntity<byte[]> displayFile(int itemId) throws FileNotFoundException{
		InputStream in = null;
		ResponseEntity<byte[]> entity = null;
		
		//파일 미리보기를 위해 DB에 저장된 해당 번호에 파일 이름 가져오기
		String fileName = itemService.getPicture(itemId);
		log.info("fileName : " + fileName);
		
		try {
			String formatName = fileName.substring(fileName.lastIndexOf(".") + 1); // 확장자 추출
			MediaType mType = getMediaType(formatName); // 이미지인지 아닌지 판단.
			HttpHeaders headers = new HttpHeaders();
			
			//File.separator -> '/' 이런 애
			in = new FileInputStream(resourcesPath + File.separator + fileName);
			if(mType != null) {
				headers.setContentType(mType);
			}
			entity = new ResponseEntity<byte[]>(IOUtils.toByteArray(in), headers, HttpStatus.CREATED);
		} catch (IOException e) {
			e.printStackTrace();
			entity = new ResponseEntity<byte[]>(HttpStatus.BAD_REQUEST);
		} finally {
			try {
				in.close();
			}catch(IOException e) {
				e.printStackTrace();
			}
		}
		return entity;
	}
	
	**// 해당 파일의 확장자 뽑아내기**
	public MediaType getMediaType(String formatName) {
		if(formatName != null) {
			if(formatName.toUpperCase().equals("JPG")) {
				return MediaType.IMAGE_JPEG;
			}
			if(formatName.toUpperCase().equals("GIF")) {
				return MediaType.IMAGE_GIF;
			}
			if(formatName.toUpperCase().equals("PNG")) {
				return MediaType.IMAGE_PNG;
			}
		}
		return null;
	}
	
	**// 이미지 수정하기 메소드**
	@RequestMapping(value="/modify", method = RequestMethod.POST)
	public String itemModify(Item item, Model model) throws IOException {
		MultipartFile file = item.getPicture();
		
		if(file != null && file.getSize() > 0) {
			log.info("originalName : " + file.getOriginalFilename());
			log.info("size : " + file.getSize());
			log.info("contentType : " + file.getContentType());
			
			String createdFileName = uploadFile(file.getOriginalFilename(), file.getBytes());
			item.setPictureUrl(createdFileName);
		}
		
		itemService.modify(item);
		model.addAttribute("msg", "수정이 완료되었습니다");
		return "item/success";
	}
}

Service

package kr.or.ddit.controller.file.item01.service;

import java.util.List;

import javax.inject.Inject;

import org.springframework.stereotype.Service;

import kr.or.ddit.mapper.ItemMapper;
import kr.or.ddit.vo.Item;

@Service
public class ItemServiceImpl implements ItemService {
	
	@Inject
	private ItemMapper mapper;
	
	@Override
	public void register(Item item) {
		mapper.create(item);
	}

	@Override
	public List<Item> list() {
		return mapper.list();
	}

	@Override
	public Item read(int itemId) {
		return mapper.read(itemId);
	}

	@Override
	public String getPicture(int itemId) {
		return mapper.getPicture(itemId);
	}

	@Override
	public void modify(Item item) {
		mapper.modify(item);
	}

}

Mapper

package kr.or.ddit.mapper;

import java.util.List;

import kr.or.ddit.vo.Item;

public interface ItemMapper {
	public void create(Item item);
	public List<Item> list();
	public Item read(int itemId);
	public String getPicture(int itemId);
	public void modify(Item item);
}

Mapper(SQL)

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "<https://mybatis.org/dtd/mybatis-3-mapper.dtd>">
 <mapper namespace="kr.or.ddit.mapper.ItemMapper">
 
 <!-- 파일 등록하는 쿼리 -->
 	<insert id="create" parameterType="item">
 		insert into item(
 			item_id, item_name, price, description, picture_url
 		) values (
 			seq_item.nextval, #{itemName}, #{price}, #{description}, #{pictureUrl}
 		)
 	</insert>
 	
 	<!-- 파일 목록 출력하는 쿼리 -->
 	<select id="list" resultType="item">
 		select
 			item_id, item_name, price, description, picture_url
 		from item
 		order by item_id desc
 	</select>
 	
 	**<!-- 해당 item 번호에 대한 정보 가져오기 쿼리 -->**
 	<select id="read" parameterType="int" resultType="item">
 		select
 			item_id, item_name, price, description, picture_url
 		from item
 		where item_id = #{itemId}
 	</select>
 	
 	**<!-- 파일 이름 가져오기 -->**
 	<select id="getPicture" parameterType="int" resultType="String">
 		select picture_url
 		from item
 		where item_id = #{itemId}
 	</select>
 	
 	**<!-- 파일 수정하기 쿼리 -->**
 	<update id="modify" parameterType="item">
 		update item
 		set
 			item_name = #{itemName},
 			price = #{price},
 			description = #{description},
 			picture_url = #{pictureUrl}
 		where item_id = #{itemId}
 	</update>
 </mapper>

JSP 페이지

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h2>Modify</h2>
	<form action="/item/modify" method="post" enctype="multipart/form-data">
		<input type="hidden" name="itemId" value="${item.itemId }">
		<input type="hidden" name="pictureUrl" value="${item.pictureUrl }">
		<table>
			<tr>
				<td>상품명</td>
				<td>
					<input type="text" name="itemName" id="itemName" value="${item.itemName }">
				</td>
			</tr>
			<tr>
				<td>가격</td>
				<td>
					<input type="text" name="price" id="price" value="${item.price }">
				</td>
			</tr>
			<tr>
				<td>파일</td>
				<td>
					<img src="/item/display?itemId=${item.itemId }" width="210" height="240">
				</td>
			</tr>
			<tr>
				<td>파일</td>
				<td>
					<input type="file" name="picture" id="picture">
				</td>
			</tr>
			<tr>
				<td>개요</td>
				<td>
					<textarea rows="10" cols="30" name="description" id="description">${item.description }</textarea>
				</td>
			</tr>
		</table>
		<div>
			<button type="submit" id="btnModify">Modify</button>
			<button type="button" id="btnList" onclick="javascript:location.href='/item/list'">List</button>
		</div>
	</form>
</body>
</html>

해당 상품을수정해보자

Untitled

파일을 코알라로 삽입한 후 등록 버튼을 누르면

Untitled

코알라로 잘 변경된 것을 확인할 수 있다.

Untitled