처음부터 차근차근
기업형 mvc 모델과 파일 업로드, String.join() 본문
기업형 mvc 모델
(패키지 따로 만들기)controller -> servlet class
service class 객체 만들어서 함수 호출하고 그 값 table class 객체 만들어서 대입한 후
request.setAttribute('a', a);.
그다음 jsp 파일 forwarding.
IndexController - index.jsp(메인) 화면에 출력하는 controller
별다른 내용없고 forwarding만함
view -> jsp 파일(WEB-INF 디렉터리 아래)
model ->
(패키지 따로 만들기)service class - 실질적인 서비스를 담당하는 class
데이터베이스 관련 내용 들어감.
안에 들어있는 함수들은 최대한 함수를 재사용해서 구현.
예를들어서 return 아래에있는함수(); 이렇게
(패키지 따로 만들기)table class - getter, setter, 생성자, toString()함수
view class
파일 업로드
인코드 방식
1. url 인코딩 방식
html form을 통해 데이터를 웹 서버로 submit 할 때 enctype을 생략했거나 enctype="application/x-www-form-urlencoded" 이면 사용되는 기본 인코딩 방식이다.
웹 서버에 데이터를 문자열로 전송한다.
쿼리 스트링 모양이다.
ex) name=ksy&age=22&id=1
2. multipart/form-data
웹 서버에 파일을 전송할 때 사용하는 인코딩 방식이다.
form에 enctype="multipart/form-data"를 쓰면 사용되는 인코딩 방식이다.
파트로 나눠서 웹서버에 전송한다.
ex) content-disposition : form-data; name="id"
1
content-disposition : form-data; name="name"
ksy
content-disposition : form-data; name="file"; filename="test.jpg"
6545G54564E452...
form에 enctype만 추가한다고 웹 서버에 파일이 전송되지 않는다.
파일을 전송하려면 파일 관련 설정을 해야한다.
파일 관련 설정 방법 2가지
1. web.xml 사용
<multipart-config>
<location>/tmp</location>
<max-file-size>20848820</max-file-size>
<max-request-size>20848820</max-request-size>
<file-size-threshold>1048576</file-size-threshold>
</multipart-config>
2. annotation 사용
@MultipartConfig(
fileSizeThreshold = 1024*1024,
maxFileSize = 1024*1024*50,
maxRequestSize = 1024*1024*50*5
)
fileSizeThreshold : (1kb * 1kb = 1mb) 파일 크기가 1mb를 넘을 경우에는 서버 메모리가 아닌 디스크를 사용해서 일시저장한다.
maxFileSize : (1kb * 1kb * 50 = 50mb) 보낼 수 있는 하나의 파일 사이즈 최대 크기는 50mb이다.
maxRequestSize : (1kb * 1kb * 50 * 5= 250mb = 250mb) 전체 파일 사이즈 최대 크기는 250mb이다.
단일 file 업로드
html 코드
<form action="addPeople" enctype="multipart/form-data">
<input type="file" name="file_n">
</form>
servlet class에서 file 받기
Part filePart = request.getPart("file_n"); // 바이너리를 넘겨주는 것
InputStream fis = filePart.getInputStream(); // 바이너리 받는 stream == System.in
// 전달 받은 파일의 저장 경로는 절대 경로를 지정해줘야함.(상대 경로 x)
// getRealPath : root를 통한 상대경로를 넘겨주면 그 시스템에 있는 절대경로(물리경로)를 반환하는 함수
String realPath = request.getServletContext().getRealPath("/upload"); // c:Users/user/....
String fileName = filePart.getSubmittedFileName(); // 파일명 대입
String filePath = realPath + File.separator + fileName;// 실제 파일 경로! pathSeparator == \
FileOutputStream fos = new FileOutputStream(filePath); // 바이너리 출력하는 stream
int size = 0; // 읽어온 데이터 byte의 개수
byte[] buf = new byte[1024]; // 1kb buffer
while((size = fis.read(buf)) != -1) { // 파일을 1kb씩 읽음. file 끝까지 다 읽으면 -1반환
fos.write(buf, 0, size); // 정해놓은 filePath에 1byte씩 내용을 적어넣음
}
//fis.read(buf) : 마지막까지 버퍼 크기만큼 다 쓰는거
//fis.read(buf, 0, size) : 버퍼 지정한 크기만큼 쪼개서 쓰는거 // 이게 훨씬 속도면에서 빠름
fos.close();
fis.close();
다중 파일 업로드
html 코드
<form action="addPeople" enctype="multipart/form-data">
<input type="file" name="file_n">
<input type="file" name="file_n">
</form>
servlet class에서 file 받기
Collection<Part> parts = request.getParts();
StringBuilder builder = new StringBuilder(); // db에 넣을 문자열 구하기(filename, filename, filename... 이런식으로 넣을 예정)
for (Part p : parts) {
if(p.getName().equals("file_n")) continue;
// 두개의 파일 중 하나만 들어왔을 경우 안들어온 file의 size는 0임. 하나만 등록되거나 아무것도 등록안됬을 때도 error나지 않음
if(p.getSize() == 0) continue;
Part filePart = p;// 바이너리를 넘겨주는 것
InputStream fis = filePart.getInputStream(); // 바이너리 받는 stream == System.in
// 전달 받은 파일의 저장 경로는 절대 경로를 지정해줘야함.(상대 경로 x)
// getRealPath : root를 통한 상대경로를 넘겨주면 그 시스템에 있는 절대경로(물리경로)를 반환하는 함수
String realPath = request.getServletContext().getRealPath("/upload"); // c:Users/user/....
String fileName = filePart.getSubmittedFileName(); // 파일명 대입
String filePath = realPath + File.separator + fileName;// 실제 파일 경로! pathSeparator == \
File path = new File(realPath);
if(!path.exists()) { // realPath가 존재하지 않으면
path.mkdirs(); // 부모 path나 내 path가 없으면 알아서 만들어줌
}
builder.append(fileName);
builder.append(",");
FileOutputStream fos = new FileOutputStream(filePath); // 바이너리 출력하는 stream
int size = 0; // 읽어온 데이터 byte의 개수
byte[] buf = new byte[1024]; // 1kb buffer
while((size = fis.read(buf)) != -1) { // 파일을 1kb씩 읽음. file 끝까지 다 읽으면 -1반환
fos.write(buf, 0, size); // 정해놓은 filePath에 1byte씩 내용을 적어넣음
}
//fis.read(buf) : 마지막까지 버퍼 크기만큼 다 쓰는거
//fis.read(buf, 0, size) : 버퍼 지정한 크기만큼 쪼개서 쓰는거 // 이게 훨씬 속도면에서 빠름
fos.close();
fis.close();
}
builder.delete(builder.length() - 1, builder.length()); // 마지막 콤마 빼기
// 나중에 people.setFiles(builder.toString()); 해서 db에 값 추가
+ tomcat은 WebContent를 Root(/)로 본다.
그래서 /upload 는 workspace 상에서 WebContent / upload 디렉터리를 뜻함.
+ 저장된 파일은 workspace에서는 보이지 않는다.
절대 경로에 저장되기 때문임...
String.join(",", 문자열리스트);
: 리스트의 원소들 사이에 ,를 찍어 새 문자열 반환
ex) a b c d e
->a, b, c, d, e
출처 : https://www.youtube.com/playlist?list=PLq8wAnVUcTFVOtENMsujSgtv2TOsMy8zd 변형 및 요약