[Spring Framework] 11강 - static file 처리와 File Upload

seb Incode·2022년 4월 18일
1

Spring Framework

목록 보기
11/22
post-thumbnail

학습 내용

  • Static web resource 처리
  • 파일업로드

학습 목표

  • 웹 서비스 시 static 웹 리소스 처리 방식에 대해 알아본다.
  • 파일업로드 방시을 이해하고 구현하다.

Static Resource 처리

Static Web Resource 처리하기

  • 서버의 처리가 필요 없는 static web resources는 요청 시 서버를 거치지 않고 곧바로 응답이 필요
  • 특정 URL로 요청이 오면 static resource로 인식하고 바로 응답 수행

지금까지 우리는 Dynamic resources에 대해서만 공부하고 실습했었습니다. 요청을 보내면 서버측까지 도달해서 이런 저런 메소드를 호출하고 리턴하는 식이었죠.
하지만 어떤 요청은 서버 처리 필요 없이 바로 클라이언트로 응답할 경우가 있습니다. 예를 들어 CSS파일 등등이 있습니다. 이런 요청들을 static resources라고 합니다.

< mvc:resources mapping="/resources/**" location="/WEB-INF/resources" />

Spring에서도 static resource와 Dynamic resource를 분리하여, static resources 응답을 빠르게 해줄 수 있도록 지원합니다. 바로 위의 태그입니다. 이 태그를 쓰면 Front-controller단에서 static resources를 빠르게 처리해줍니다.
위 태그는 servlet-context.xml에 작성하면 됩니다.
해당 태그에는 두 개의 속성이 있습니다.
1) mapping 속성 : URL 경로를 의미합니다.
즉, URL에 /resources를 달고 오면 "아 이건 static resources 요청이구나" 이렇게 판단하는 겁니다.
2) location 속성 : static resources를 탐색하는 디렉토리 경로입니다.

파일 업로드

파일 업로드 시 HTML 파일

<form method="post" enctype="multipart/form-data">
  ...
</form>

파일 업로드 기능은 일반적으로 HTML에서는 form 태그를 사용하고 enctype 값을 "multipart/form-data" 넣어줍니다.

멀티파트 지원 기능을 사용하기 위해서 MultipartResolver를 스프링 설정으로 등록

  • MultipartResolver는 encType이 multipart/form-data 형식으로 데이터가 전송되었을 경우 해당 데이터를 Spring MVC에서 사용할 수 있도록 변환해준다.

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<property name="maxUploadSize" value="104857600" /> <!-- 100MB -->
    <property name="defaultEncoding" value="UTF-8"/>
</bean>

파일 업로드를 사용하려면 DispatcherServlet xml 파일에 bean으로 등록해야합니다.
그리고 여러가지 속성을 설정할 수 있습니다.

Dependency 추가

  • CommonsMultipartResolver는 Apache Commons FileUpload를 사용
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>
<form method="post" enctype="multipart/form-data" action="/bbs/upload">
  <input type="text" name="name"/>
  <input type="file" name="file" />
  <input type="submit" value="전송" />
</form>

dependency도 추가해야합니다.
HTML 작성은 input 태그 type 값을 "file"로 적어주시면 됩니다.

Controller File Upload Logic 추가

@RequestMapping("/upload")
public String doUpload(@RequestParam("name") String name, @RequestParam("file") MultipartFile file, Model model){
	if(!file.isEmpty()){
    	File.tmpFile = new File("c:\\", file.getOriginalFilename());
        file.transferTo(tmpFile);
    }
    Model.addAttribute("fileNamek", name);
    return "upload_ok";
}

파일을 웹으로부터 받았을 때, Java에서는 MultipartFile이라는 타입으로 파일 데이터를 받을 수 있습니다.
그리고 이 파일을 파일시스템에 저장하기 위해서 transferTo()를 사용합니다.
이렇게 하면 파일 업로드가 실제로 이루어집니다.

MultipartFile의 주요 메소드

Command 객체로 받아오기

  • 일반 HttpServletRequest와 동일하게 MultipartFile도 Command 객체로 받아올 수 있다.
  • 멤버변수의 타입이 MultipartFile로 선언되어야 한다.
public class UploadCommand{
	private String name;
    private MultipartFile file;
    //
    public String getName(){
    	return this.name;
    }
    public void setName(String name){
    	this.name = name;
    }
    public MultipartFile getFile(){
    	return this.file;
    }
    public void setFile(MultipartFile file){
    	this.file = file;
    }
}

HTML에서 데이터를 받아올 때 파일 데이터도 Command 객체로 받아올 수 있습니다. 일단 이렇게 VO(도메인 객체)를 정의합니다.

@ReqeustMapping("/doUpload")
public ModelAndView doUpload(UploadCommand command) throws IllegalStateException, IOExption{
	MultipartFile uploadedFile = command.getFile();
    if(!uploadedFile.isEmpty()){
    	File file = new File("c:\\", uploadedFile.getOriginalFilename());
        uploadedFile.transferTo();	//실제 저장
    }
    ModelAndView view = new ModelAndView();
    view.setViewName("test/fileUpload");
    return view;
}

파일 저장 시 보안 사항

  • 업로드 된 파일 이름을 그대로 사용해서 저장을 하게 되면, 추후 파일 다운로드 및 보안사항에 문제가 발생한다.
  • 때문에, 아래처럼 파일 이름은 숨기고 실제 파일명은 난수화 시켜서 저장한다.
  • Display File Name과 Real File Name은 모두 Database에 저장되는 항목이다.
  • 예로, 화면에서 Oracle.exe 파일을 다운받기 위해서는 파일의 실제 명인 "189217481234781872"을 요청해야 한다.

String fileRandomName = UUID.randomUUID().toString();

  • 파일의 이름을 난수화 시키는 방법
  • 현재 시간을 기준으로 하기 때문에 중복이 될 수 없는 난수

실제 파일 이름을 난수화 시키기 위해 사용하는 함수입니다.

실습

1. Static Resource 처리

/bbs로 요청이 올 때, index.jsp 파일을 static Resource로 뿌려주는 실습입니다.

↑ URL 요청이 들어올 때 index.jsp를 뿌려줄 수 있도록 메소드를 작성합니다.

↑ index.jsp를 작성하고 이미지파일, css파일도 추가합니다.

↑ HTML 페이지가 뜨긴 하지만 사진이나 CSS파일 적용이 안된 듯 합니다.
왜냐하면 static resources 등록을 하지 않았기 때문이죠.

↑ servlet-context.xml에 태그를 추가합니다.
이렇게 설정하면, 요청이 들어왔을 때 DispatcherServlet(=front controller)가 controller를 찾지 않고, 아 이 요청은 Static Resources 요청이구나 판단해서 바로 경로를 찾아서 반환해줍니다.

↑ xml 수정 후 다시 요청을 보냈을 때 결과입니다.
사진이 제대로 출력됩니다. CSS파일은 티가 잘 안나지만 padding 설정된 게 좀 보이실 겁니다ㅎㅎ;

2. 파일 업로드

↑ Servlet-context.xml(DispatcherServlet 설정 파일)에 BEAN를 등록합니다.
class 속성 값은 "CMR" 치시고 Ctrl+space bar 누르시면 나와요~

↑ pom.xml(maven 프로젝트 설정파일)에서 commons-fileupload 라이브러리를 추가합니다.
파일 위치는 프로젝트 루트에 있어요~

↑ 컨트롤러를 하나 더 생성하고 코드를 작성합니다.

↑ 요청을 날립니다.

↑ 성공적으로 upload_ok.jsp가 뜹니다.

↑ Controller에 작성했던 파일 저장 경로("C:\upload")에 들어가 보면 실제로 파일이 저장되어 있습니다.

0개의 댓글