Languages/java

[JAVA] 파일업로드01_해보기

뱅타 2021. 4. 12. 22:23

파일 전송해보기

jsp : <form>에서 method를 post로 해야한다.

file은 문자열이 아닌 2진데이터(byte)형식이기 때문에 requestBody에 데이터들을 담아서 보내주어야 한다.

body를 생성하려면 method를 post방식으로 사용해야함.

inline에 2진데이터를 첨부할 수 없다. requestInline은 String만 가능하다.

그래서 method = post로 바디를 생성해서 보낸다.

아래 사진처럼 input type="file"로만 지정해서보내면 값을 받아올 수 없다. 실제로 출력하면 문자열이 넘어간다.

그래서 form태그에 enctype을 지정해 준다.(encodingtype)

enctype = "multipart/form-data"

enctype을 설정해 주어야 한다.

이렇게 기본 urlencode에서 multipart/form-data로 mimetype을 설정

multipart로 나누면 여러개의 파일을 보낼 수 있다.(text도 가능)

multipart

  • body가 해당 파트 만큼 쪼개진다.

    위의 사진에서는 파트가 두개.

클라이언트의 요청을 보면 content-Type의 boundary 이후에 이상한 문자열이 들어가 있는것이 보임.

이 boundary 다음에 나오는 문자가 나누는 영역을 나타낸다.

이렇게!

*주의 part는 아무값도 입력하지 않아도 형성된다.

파일 업로드 시 해야할 것

  • body 생성 (method = post)
  • mime 설정하기(파트 나누기(enctype))

multipart는 모든 값들을 param으로 가지고 올 수 없다.

이렇게 파람으로 가지고 오면 null이 뜬다.

part api를 사용해서 sever단에서 값을 받아보자.

3.0 이후버전에 쓸수 있다.

파트가 받을 수 있는 형식을 알려줌.

part api는 3.0 버전 이후에 사용가능함을 알아두자.

파라미터로 request part의 name을 요구한다.

name을 잘 보면 jsp의 <input>태그의 name 값과 동일함을 알 수 있다.

파트의 name 값을 결정하는것 역시 <input>태그의 name이다.

만약 part를 쓰고 name값이 모두 같은데도 안된다면 버전을 한번 의심해 보아야 한다.

web.xml의 servlet에 들어가서 <multipart-config> 태그를 추가해 보자.

multipart-config 자체가 3.0에서 운영되는 것이기 때문에 추가해 주면

2.5 → 3.0대로 사용하겠다 라는 뜻이 된다.

이렇게 설정해 주고 다시 실행한다면

파라미터와 파트 둘다 잘 잡힌다.(위의 null은 name을 잘못 적어서 나왔다...)

그럼 <multipart-config>는 머하는 녀석일까?

이 녀석은

업로드할때 파일 크기를 제한해서 읽을 수 있는지 없는지를 결정해 주는 녀석이다.

  • max file size

하나의 파일의 최대 사이즈

  • max request size

모든 파일의 최대 총합 사이즈

  • location

10기가의 데이터를 100mb로 나눠서 받는다. 이 받는 단위를 청크라고 하는데

청크데이터들이 저장될 수 있는 공간이 필요하다.

1청크당 100mb면 1기가면 10번 이런 식으로 어느 공간에 값들을 담았다가 보내는 형식이다.

그래서 그 청크들이 1 +2 +3... 등등.. 처럼 어디가에 저장되는 공간을 말한다.

디폴트는 vm의 임시폴더를 그대로 쓴다.

  • file size threshold / default=10kb

업로드 되는 파일의 크기가 작으면 임시로 저장할 필요가 없어진다. 그 임계치를 설정하는 것.

임계치 이상이면 location에 저장됨. 이하면 memory에 저장된다.

임계치 이상일 때 청크가 생성된다.

우선 디폴트로 하자. (아무것도 적지 않으면 모든 값들이 default로 유지된다)

따로 만들어 둔 @RequestMapping과 @RequestParam을 써 보았다.

RequestMapping은 servlet의 @webServlet과 같은 것이고

RequestParam의 경우는 parameter 가져오는 것과 동일하다.

파일 데이터의 경우 DB에 직접 저장할 수도 있지만... 보통 latency time을 줄이기 위해서 해당 이미지의 메타 데이터만 저장한다.

**latencyTime은 클라이언트가 요청할 때 한번, sever단에서 DB로 데이터를 옮기거나 받을 때 나온다.

지금은 db에 해당 이미지의 메타 데이터만을 저장해 보자(db의 image컬럼이 varchar2타입이다.)

그래서 fileupload를 할 때

  1. 미들티어 어딘가에 저장할 수 있어야 한다.
  1. 저장 후 그 메타데이터를 뽑아야 한다.
  1. 서버에 보내야 한다.

를 유의해서 작성해 보자.

part로 가져온 데이터의 어떤 것들을 가지고 올 수 있는지 한번 살펴보자.

inputstream으로 파일을 읽기 전에 저장할 공간을 설정해 주자

inputStream으로 들고온 데이터를 읽기 전에 읽은 파일을 저장할 공간을 마련해 보자.

이렇게 폴더를 만들고 저장할 폴더에게 경로를 입력해야 한다.

하지만 우리는 해당폴더의 절대경로를 모르기때문에 ServletContext를 사용해서 절대경로를 구한다.

이렇게 사용하면 하드코딩 하지 않고 서버에 따른 경로를 받아올 수 있다.

원본파일과 같은 이름으로 저장해 보자.

**주의 getSubmittedFileName()의 경우 3.0이상에서만 쓰인다.(조금 후에 이 메서드를 쓰지 않고 파일 이름을 가져오는 방법을 한번 살펴보자)

jsp에서 이미지파일만 올릴 수 있게 view단에서 검증을 한번 걸어준다.

이미지만 업로드하기 제한! accept="image/*"

저장공간도 만들었고 이제 input, outputStream으로 데이터를 읽고 해당 폴더에 저장해 보자.

인풋 아우풋 스트림 사용해서 파일 옮기기

매번 이 부분이 잘 이해가 안감...

각각 빨때 꼽기 딱 빨때만 꽂혀 있다.

이제 뽑아서 넣어주자.

바이트가 없을 시(stream is at the end of the file) -1을 return한다.

이렇게 설정해 준 buffer로(설정해주지 않으면 1byte 씩 읽는다. bufferedStream을 사용해도 된다.)

buffer(1024byte)가 채워질때까지 매번 맨 처음부터 -1까지

업로드 후 출력해보기

그럼 잘 뜨는것을 확인 할 수 있다.

Eclipse에서 폴더를 열어 확인해 보면 실제 이미지는 들어있지 않다.

확인해보려면 톰캣의 파일로 가서 확인해 보아야한다.

톰캣이 관리하는 실제 경로로 가서 확인해 보아야 한다.

이렇게 완료되었다...고 하고싶지만 여기까지만 작성하면 문제점들이 많이 있다.

  1. 저장하려는 폴더가 없다면 어떻게 할 것인가
  1. 실제로 이미지만 올라갈까?
  1. 널체크
  1. 버전을 타고있다.

eclipse의 특징

폴더 안에 파일이 하나도 없다면 배포할 때 버려버린다.

해당 문제점은 파일업로드02_해보기에서 확인해보자.

여기서는 요것만 알아두자.

**** fileUpload 시 해야할 것들 순서

  1. jsp(form)
  1. web.xml(설정변경)
  1. servlet(part Api사용)
728x90
반응형