ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 초보자도 간단하게 스프링으로 만드는 파일업로드 기능(spring file upload)
    Study/JavaScript 2023. 3. 16. 18:26
    반응형

    오늘은 초보자도 쉽고 간편하게 만들어 보는 파일 업로드 기능 만들어 볼까함

     

    1.설명

    백단은 sql.xml -> mapper -> service -> serviceImpl ->controller 순으로 진행 된다.

    흐름은 게시판 CRUD와 비슷한 흐름으로 진행 된다고 생각하는게 좋을 듯함.

     

    2.구현

    (1)sql.xml

    DB에 이미지가 있는 폴더 경로, 파일 이름,uuid 를 저장하면 추후에 DB에서 정보를 꺼내어 동적으로 활용할 수 있는데,

    우선은 간단하게 작성하기 위해 파일이름만 DB에 넣어주었다!

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="shgas.main.service.impl.testMapper">
    	
    	<insert id="saveFile" parameterType="shgas.main.service.fileVO">
    		insert into fileSave (fileName) values(#{fileName})
    	</insert>
    	
    </mapper>

    (2)VO

    vo는 sql.xml -> mapper -> service -> serviceImpl ->controller 각각의 단계로 넘어갈때 값을 담아서 그 담단계로 넘어갈때 담아서 보내주는 역할을 한다.

    MultipartFile 타입의 변수를 선언해 주었는데, controller에서 쓰기 위함.

    MultipartFile은 클라이언트가 업로드한 File을 핸들러에서 손쉽게 다룰 수 있도록 MultipartFile 인터페이스를  제공

    인터페이스를 통해 파일의 이름과 실제 데이터, 파일크기 등을 구할 수 있음.

    package shgas.main.service;
    
    import org.springframework.web.multipart.MultipartFile;
    
    public class fileVO {
    	
    	private String fileName;
    	private MultipartFile uploadFile;
    	
    	public String getFileName() {
    		return fileName;
    	}
    	public void setFileName(String fileName) {
    		this.fileName = fileName;
    	}
    	public MultipartFile getUploadFile() {
    		return uploadFile;
    	}
    	public void setUploadFile(MultipartFile uploadFile) {
    		this.uploadFile = uploadFile;
    	}
    	
    }

    (3)mapper인터페이스

    참고로 mapper.xml의 id로 지정한 이름과 mapper인터페이스의 이름이 같아야 마이바티스에서 mapping을 해

    package shgas.main.service.impl;
    
    
    import java.util.List;
    
    import egovframework.rte.psl.dataaccess.mapper.Mapper;
    import shgas.main.service.fileVO;
    import shgas.main.service.vo;
    
    @Mapper("testMapper")
    public interface testMapper {
    	
    	public void saveFile(fileVO vo);
        
    }

    (3)service인터페이스

    service코드는 mapper인터페이스 코드와 유사한데, 굳이 service인터페이스를 쓰는 이유는

    mapper는 DB접근에 대한 메서드를 만들고 service인터페이스는 말그대로 고객에게 서비스하기 위해 만드는 비지니스로직으로 비지니스로직을 구분함.

    즉, 고객에게 보여줄 필요가 없는 부분이지만 개발상 백단에서 DB에서 특정 정보를 꺼내올때 mapper에서만 비지니스로직을 작성하고 service에는 작성하지 않을수도 있고, 반대로 DB를 끌어올 필요는 없지만 고객에게 어떠한 서비스를 하기 위하여 작성할때 service인터페이스에만 비지니스로직을 작성 할 수 있다

    package shgas.main.service;
    
    import java.util.List;
    
    public interface testService {
    	
    	public void saveFile(fileVO vo);
    
    }

    (4)serviceImpl

    service인터페이스를 상속받아 비지니스 로직을 직접 컨트롤 할수 있는 구현체 부분 임.

    실직적인 비지니스로직은 serviceImpl에서 짠다고 보믄 됨 

    package shgas.main.service.impl;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import shgas.main.service.fileVO;
    import shgas.main.service.testService;
    import shgas.main.service.vo;
    
    @Service
    public class testServiceImpl implements testService{
    
    	@Autowired
    	private testMapper mapper;
    
    	@Override
    	public void saveFile(fileVO vo) {
    		mapper.saveFile(vo);
    	}
    }

    (5)controller

    젤 중요한 부분이라 코드 한줄한줄 설명을 주석으로 달았음

    	@PostMapping("/uplodeFile.do")
    	public String uplodeFile(@ModelAttribute("vo") fileVO vo)throws Exception {
    	   //@ModelAttribute는 VO를 객체화 시켜서 jsp로 넘겨줌 
           //이때 괄호안에 text는 jsp에서 값을 부르는 별명이라고 생각하면 됨
           //여기서는 VO를 객체로 만들어 줘야해서 @ModelAttribute 지정함
          
            
    		String fileName = null;
    		MultipartFile file = vo.getUploadFile();//위에 fileVO객체를 통해 MultipartFile 기능을 쓸수 있게 내용을 담아줌
    		if (!file.isEmpty()) { //file객체가 비어있지 않다면
            
    		String originalFileName = file.getOriginalFilename(); //파일의 실제 이름
    		String ext =FilenameUtils.getExtension(originalFileName); //파일의 확장자
    		UUID uuid = UUID.randomUUID(); //파일의 새로운 닉네임 같은거....
    		fileName = originalFileName; //랜덤값+파일의 실제 이름+파일의 확장자 이렇게 붙여서 파일명을 새롭게 만들고 
            							//DB에 담아주는게 좋으나 나는 간단하게 작성을 위하여 파일명만 지정 
    		file.transferTo(new File("c:\\upload\\"+fileName)); //new File 객체를 통해 file객체를 만들고
            							//"c:\\upload\\"지정해준 경로에 파일새로만들기
    		}
    		
    		vo.setFileName(fileName); //지정해준 파일명을 vo에 담아줌
    		service.saveFile(vo); // 담아준 vo를 비지니스로직에 태워보냄
    		
    		
    		return ""; //특정 jsp페이지로 지정해도되나 나는 따로 지정을 안하여 controller가 실행한뒤 404에러페이지가 나온다
        
    	}

    참고로 uuid 는 랜덤으로 만들어지는 파일의 닉네임이라 생각하는게 좋을듯하다.

    왜냐하면 파일을 저장할때 이름이 같을수 있기 때문에 램덤으로 임의 숫자와 문자의 조합을 만들어 내어 폴더이름에 추가로 붙여주어 파일의 중복을 막아준다!

    (5) JSP

    1번-controller에 있는 코드를 실행 해주기 위해서 form형식을 이용하여 백단에 데이터를 전송함

    action에는 controller에서 실행하고자 하는 URL을 기입, method는 get방식과 post방식중 선택해야 되는데,

    보통은 조회할때는 get방식을 사용하고 클라이언트측에서 정보를 보낼때는 post방식으로 보냄

    encType은 form데이터가 서버로 넘어갈때 어떤방식으로 읽으면 되는지 알려주는 부분이라 생각하면 됨

    multipart/form-data는 파일이나 이미지를 서버로 전송할 때 주로 사용함.

     

    2번-form내용안에 input type="file"로 지정을 해야 클라이언트가 선택한 파일을 읽어올 수 있음.

     

    3번-마지막으로 submit으로 form을 제출 해야됨.

    간혹가다가 button형식으로 하시는 분이 있는데, form 제출이 안됨

    <%@ 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>
    <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
    </head>
    <body>
    
    <form action="/uplodeFile.do" method="post" encType="multipart/form-data">
    <div>파일업로드 test!!!</div>
    <div><input type="file" name="uploadFile"></div>
    <button type="submit" >파일업로드</button>
    </form>
    
    
    </body>
    
    
    </html>

     

    3.결과화면

    ***파일선택하는 화면***
    ***실행전 폴더에 암것도 없음***
    ***실행후 이미지 파일이 생성됨***
    ***DB에 파일명이 insert&nbsp; 됨***

    반응형

    댓글

Designed by Tistory.