스노우보드 참 좋아하는데 맨날 키보드 앞에만 있네

[spring/STS] 게시물의 파일첨부 본문

개발/Java, SpringFramework

[spring/STS] 게시물의 파일첨부

워너-비 2017. 10. 27. 10:40

<!-- 본 포스팅은 개인공부를 위한 용도로 잘못된 정보가 있을 수 있습니다. 오류 발견시 댓글 환영합니다. -->

Spring을 이용한 게시물의 첨부파일 기능




Spring/STS 환경에서 게시물 작성시 파일을 첨부하고, 화면에서 보여주거나 다운로드할 수 있는 기능을 구현하고자 한다.


회원가입, 게시판, 댓글 기능 구현에 비해 어렵게 느껴질 수 있지만.. 이정도 쯤이야




게시물의 첨부파일 모듈 구현순서


1. 첨부파일의 등록

2. 첨부파일을 등록하는 방식은 크게 <form>, Ajax의 형태가 존재한다.

3. 첨부파일의 반환과 화면 출력

4. 파일 업로드 정보를 테스트한 후 파일 정보를 다시 브라우저로 전송한다.

5. 첨부파일의 저장

6. 실제로 파일을 저장한다. 이 경우 고유한 파일이름, 경로, 썸네일에 주의하여 처리한다.

7. 첨부파일의 조회

8. 첨부파일이 제대로 화면에서 볼 수 있도록 작성한다. 이미지 파일과 일반 파일을 구분해서 큰 화면으로 보거나, 다운로드 할 수 있도록 조치

9. 첨부파일의 삭제

10. 첨부파일이 삭제될 때 데이터베이스와 관련하여 트랜잭션 처리가 필수적이며, 파일과 관련해서 저장된 파일을 같이 삭제하도록 처리한다.








라이브러리 추가


파일업로드를 위한 라이브러리와 이미지를 축소할 수 있는 imgScalr 라이브러리를 선언한다.


pom.xml

 <dependency>

<groupId>commons-fileupload</groupId>

<artifactId>commons-fileupload</artifactId>

<version>1.3.1</version>

</dependency>


<dependency>

<groupId>org.imgscalr</groupId>

<artifactId>imgscalr-lib</artifactId>

<version>4.2</version>

</dependency>




파일 업로드 관련 bean 설정


스프링MVC에서 파일 업로드를 처리하기 위해서는 파일 업로드로 들어오는 데이터를 처리하는 객체가 필요하다.

multipartResolver 설정을 해주면 개발자는 이후 controller로 들어오는 데이터에 대한 처리만 해주면 된다.


또한 업로드 파일을 저장하기 위해 서버의 파일저장 경로를 설정해주어야 한다.

업로드 된 파일의 보관은 파일 시스템을 사용하거나 데이터베이스를 이용할 수 있다.

본 예제는 현재 컴퓨터 하드디스크에 저장한다.


웹 설정파일인 servlet-context.xml에서 다음과 같이 설정해준다.


servlet-context.xml

<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

<beans:property name="maxUploadSize" value="10485760"></beans:property>

</beans:bean>


<beans:bean id="uploadPath" class="java.lang.String">

<beans:constructor-arg value="/Users/Wannab/Desktop/upload">

</beans:constructor-arg>

</beans:bean> 


<property>의 maxUploadSize 속성은 파일 업로드의 크기를 제한한다. 약 10MB정도 크기인 10485760바이트로 설정해주었다.

그 외 <property>는 maxInMemorySize, defaultEncoding가 있다.


uploadPath라는 id를 가진 문자열이 스프링의 빈으로 설정한다.

문자열의 값은 바탕화면의 upload폴더 경로로 지정해주었다. 본인이 희망하는 폴더 경로로 지정해주면 된다.

작성된 문자열은 controller에 주입하여 사용한다.








GET방식으로 입력되는 경우 사용하는 JSP 파일 작성


uploadForm.jsp

 <form id='form1' action="uploadForm" method="post"

enctype="multipart/form-data">

<input type='file' name='file'> <input type='submit'>

</form>


form의 enctype 속성값인 multipart/form-data는 multipart 방식으로 데이터가 전달된다.








업로드를 위한 Controller 작성


UploadController.java


import java.io.File;

import java.util.UUID;


import javax.annotation.Resource;


import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

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;


@Controller

public class UploadController {

private static final Logger logger = LoggerFactory.getLogger(UploadController.class);


@Resource(name = "uploadPath")

private String uploadPath;


@RequestMapping(value = "/uploadForm", method = RequestMethod.GET)

public void uploadForm() {

}


@RequestMapping(value = "/uploadForm", method = RequestMethod.POST)

public void uploadForm(MultipartFile file, Model model) throws Exception {


logger.info("originalName: " + file.getOriginalFilename());

logger.info("size: " + file.getSize());

logger.info("contentType: " + file.getContentType());


String savedName = uploadFile(file.getOriginalFilename(), file.getBytes());


model.addAttribute("savedName", savedName);


}


@RequestMapping(value = "/uploadAjax", method = RequestMethod.GET)

public String uploadFile(String originalName, byte[] fileData) throws Exception {


UUID uid = UUID.randomUUID();


String savedName = uid.toString() + "_" + originalName;


File target = new File(uploadPath, savedName);


FileCopyUtils.copy(fileData, target);


return savedName;


}

}



uploadFile()은 원본 파일의 이름과 파일 데이터를 byte[]로 변환한 정보를 파라미터로 처리하여 실제 파일을 업로드 한다.


uploadFile()에 사용한 UUID는 중복되지 않는 고유한 키 값을 설정할 때 사용한다.

고유한 키 값을 설정함으로써 동일한 경로에 동일한 이름의 파일을 업로드 할 때 발생하는 문제를 해결할 수 있다.


uploadFile() 내부에서 실제 파일 처리는 스프링에서 제공하는 FileCopyUtils를 이용한다.

FileCopyUtils는 org.springframework.util 패키지에 설정된 클래스로 파일 데이터를 파일로 처리하거나, 복사하는 등의 작업에 사용된다.




위의 코드를 이용해서 업로드를 실행하면 해당 경로에 고유한 UUID 값이 붙은 첨부파일이 생성되는 것을 볼 수 있다.


첨부파일 생성 (99c3c4cc-a596-439c-8f8a-42758b269614_테스트파일.hwp)









한글파일 이름이 깨지는 경우


파일 이름에 한글이 들어갈때, 깨지는 현상이 발생할 수 있는데, 이를 해결하기 위해서는 한글 처리용 필터를 적용한다.

UTF-8은 유니코드를 사용한 인코딩 방식이다.


/WEB-INF/web.xml

<filter>

  <filter-name>encoding</filter-name>

  <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

  <init-param>

   <param-name>encoding</param-name>

   <param-value>UTF-8</param-value>

  </init-param>

</filter>

<filter-mapping>

  <filter-name>encoding</filter-name>

  <url-pattern>/*</url-pattern>

</filter-mapping> 




Comments