본문 바로가기
네이버클라우드/JAVA 웹 프로그래밍

JAVA 59일차 (2023-08-14) 자바 프로그래밍_57. 파일 업로드 다루기 - multipart/form-data POST 요청 파라미터 인코딩_개인프로젝트 - 마트 관리 시스템

by prometedor 2023. 8. 15.
## 57. 파일 업로드 다루기 - multipart/form-data POST 요청 파라미터 인코딩

- apache.org의 라이브러리를 이용하여 multipart/form-data 파라미터를 다루는 방법
- Servlet API를 이용하여 multipart/form-data 파라미터를 다루는 방법
- 네이버클라우드 mysql DBMS 사용하기

 

BoardFormServlet.java

ㄴ 해당 코드 추가

=>

ㄴ 서버 Start

=>

=>

ㄴ 게시판 > 새 글 > 내용 입력 > [파일 선택] 선택

=>

ㄴ 이미지 1개 선택

=>

=>

=>

ㄴ 등록 선택 후 개발자도구의 Payload 탭에서 filename 전달됨을 확인

 

 

Charles Proxy 로 확인하기 

ㄴ Charles Proxy 실행해두기

=>

=>

ㄴ 이미지 1개 선택

=>

ㄴ [등록] 선택

=>

=>

ㄴ Chales Proxy 에서 확인 시 boundary=---- ... 추가됨을 확인

=>

=>

 

 

여러개의 파일 업로드 하기 위한 라이브러리 추가

https://apache.org/

 

Welcome to The Apache Software Foundation!

Official ASF reports and statements, including Quarterly and Annual Reports, Vision Statement, "Apache is Open", 5-Year Strategic Plan, and more.

apache.org

ㄴ [See All Projects] 선택

=>

ㄴ Commons 선택

=>

ㄴ FileUpload 선택

=>

ㄴ Documentation 확인을 위해 창 띄워두기

 

https://central.sonatype.com/

 

Maven Central

Official search by the maintainers of Maven Central Repository.

central.sonatype.com

ㄴ commons-fileupload 1.5 선택

=>

ㄴ Gradle(short) 선택

=>

ㄴ [Copy to clipboard] 선택

=>

build.gradle

ㄴ 복사한 코드 build.gradle 스크립트 파일의 dependencies 에 붙여넣기

=>

ㄴ gradle 재설정

=>

ㄴ Refresh 해주기

=>

ㄴ 라이브러리 추가된 지 확인하기

=>

BoardFormServlet.java

ㄴ multiple 옵션 추가

=>

ㄴ 서버 Restart

=>

첨부 파일 여러개 선택하여 새 글 등록 시도

=>

ㄴ 이미지 여러 개 선택

=>

 

ㄴ 파일 2개 선택됨

ㄴ [등록] 선택

=>

=>

 

 

ㄴ 이전에 띄워둔 Documentation 이용

ㄴ User Guide 선택

=>

ㄴ 해당 코드 복사

=>

BoardAddServlet.java

=>

=>

BoardAddServlet.java

=>

=>

BoardAddServlet.java

ㄴ 예외 처리 필요

=>

BoardAddServlet.java

ㄴ try~catch 문을 통해 예외 던지기

=>

BoardAddServlet.java

ㄴ items -> parts 로 변경

ㄴ 각각의 파트에서 값을 꺼내도록 함

=>

BoardAddServlet.java

ㄴ Board 객체 생성을 위쪽으로 이동시킴

=>

BoardAddServlet.java

ㄴ 일반 데이터일 경우와 파일 데이터일 경우를 구분하여 값 꺼내기

=>

BoardAddServlet.java

ㄴ 파일 이름 확인하기위한 출력문 추가

=>

BoardAddServlet.java

ㄴ 해당 코드 제거

=>

BoardAddServlet.java

ㄴ 작성자 설정도 위쪽으로 올려주기

=>

BoardAddServlet.java

ㄴ 해당 코드 제거

=>

BoardAddServlet.java

ㄴ category -> board.getCategory() 로 변경해주기

=>

ㄴ 서버 Restart 해주기

=>

게시판 > 새 글 추가 시 첨부파일 첨부하도록 함

=>

=>

ㄴ [등록] 선택

=>

ㄴ 글 정상 등록 됨을 확인

=>

ㄴ 콘솔 확인 시 등록한 파일 이름 확인 가능

 

 

등록한 사진이 저장되도록 하기

ㄴ webapp 폴더에 upload 라는 이름의 폴더 생성

=>

ㄴ upload 라는 폴더에 board 라는 이름의 폴더 생성

=>

ㄴ 폴더가 비어있지 않도록 README.md 파일 추가해주기

=>

README.md

=>

ㄴ wtpwebapp > report-server  폴더에 upload 폴더 생성됨을 확인

 

 

BoardAddServlet.java

ㄴ 웹 애플리케이션 환경 정보를 알고 있는 객체를 꺼내고, 웹 애플리케이션 환경정보에 /upload/board 디렉토리의 실제 경로를 계산하여 추출하도록 함

=>

ㄴ 서버 Restart

=>

게시판 > 새 글 추가 시 첨부파일 첨부하도록 함

=>

=>

ㄴ [등록] 선택

=>

=>

ㄴ 실제 경로 알아내기

=>

BoardAddServlet.java

ㄴ uploadDir 출력은 주석 설정

ㄴ part.write(...) 코드 추가

=>

ㄴ java.io.File import 하기

=>

ㄴ 서버 Restart 해주기

=>

=>

ㄴ [등록] 선택

=>

ㄴ 배포 폴더에 사진 등록됨을 확인

 

 

파일 저장 시 사용할 이름 정해주기

BoardAddServlet.java

=>

ㄴ 서버 Restart 해주기

=>

=>

ㄴ [등록] 선택

=>

ㄴ 배포 폴더에 첨부한 사진이 randomUUID 값을 이용한 이름으로 저장됨

 

 

 

ㄴ 이제 사용하지 않으므로 Delete 해주기

 

ㄴ AttachedFile 이라는 이름의 클래스 생성하기

=>

AttachedFile.java

ㄴ 필드 생성 및 Getter/Setter 생성

=>

ㄴ [Select All] 선택

ㄴ [Generate] 선택

 

AttachedFile.java

ㄴ Serializable 구현해주기

ㄴ serialVersionUID 추가해주기

 

Board.java

=>

Board.java

=>

ㄴ Getter/Setter 추가해주기

 

 

BoardAddServlet.java

ㄴ AttachedFile 클래스의 객체들을 담을 수 있는 ArrayList인 attachedFiles를 생성

=>

BoardAddServlet.java

=>

BoardAddServlet.java

=>

BoardAddServlet.java

ㄴ board 객체에 attachedFiles라는 ArrayList<AttachedFile>을 설정하도록 함

 

BoardDao.java

ㄴ insertFiles 인터페이스 정의 추가

=>

MySQLBoardDao.java

ㄴ insertFiles 인터페이스 구현

=>

BoardDao.xml

ㄴ (1, 'a.gif'), (1, 'b.gif'), (1, 'c.gif') 을 foreach 문으로 구현

=>

BoardDao.xml

ㄴ collection: 순회할 컬렉션을 지정 (attachedFiles 리스트를 순회함)
ㄴ item: 순회 과정에서 현재 아이템을 담을 변수명을 지정 (file 변수에 AttachedFile 객체가 순차적으로 대입됨)
ㄴ separator: 아이템 간에 구분을 지정 (,로 각 아이템을 구분)
ㄴ (#{file.filePath}, #{no}) : 각 AttachedFile 객체의 filePath와 no 값을 MyBatis의 매개변수로 전달하기 위한 표현식

ㄴ MyBatis의 동적 SQL 기능을 활용하여 attachedFiles 리스트에 있는 첨부 파일 정보를 활용하여 SQL 쿼리를 동적으로 생성하고 실행하도록 함

 

BoardAddServlet.java

ㄴ board.getNo() 를 출력해보도록 함

=>

ㄴ 서버 Restart 해주기

=>

로그인 후 새 글 등록 (첨부파일 첨부)

=>

=>

ㄴ [등록] 선택

=>

=>

ㄴ 0 이 출력되므로 수정 필요

=>

BoardDao.xml

=>

BoardDao.xml

=>

BoardDao.xml

=>

BoardDao.xml

ㄴ useGeneratedKeys: 이 속성을 true로 설정하여 데이터베이스에서 자동으로 생성되는 키 값을 가져오도록 함
ㄴ keyColumn: 자동 생성된 키 값을 받을 컬럼의 이름을 지정 ("board_no" 컬럼을 사용하여 자동 생성된 키 값을 받음)
ㄴ keyProperty: 키 값을 저장할 객체의 프로퍼티 이름을 지정 (no라는 프로퍼티에 자동 생성된 키 값을 저장)
=> 데이터베이스에 INSERT 작업을 수행할 때 자동으로 생성된 키 값을 가져와서 board 객체의 no 프로퍼티에 저장하도록 함

 

ㄴ 서버 Restart 해주기

=>

ㄴ [등록] 선택

=>

ㄴ 23 이 출력되는 것을 확인

=>

BoardAddServlet.java

ㄴ 전과 후 비교를 위한 출력문

=>

서버 Restart 해주기

=>

=>

BoardAddServlet.java

=>

ㄴ 서버 Restart 해주기

=>

ㄴ [등록] 선택

=>

ㄴ mysql 을 실행한 터미널에서 확인 시 filepath 가 정상적으로 저장됨을 확인

 

 

상세보기 화면에서 이미지 출력하기

BoardDao.xml

ㄴ left outer join 이용

    => 앞쪽에 inner join 한 것을 다시 left outer join 하는 것

ㄴ f.board_file_no, f.filepath 추가해주기

=>

ㄴ 쿼리문을 잘 작성했는지 터미널에서 확인해보기

=>

BoardDao.xml

ㄴ <collection> 태그:
     => property: 매핑 결과를 저장할 객체의 프로퍼티 이름을 지정 (attachedFiles 리스트에 매핑 결과를 저장)
     => ofType: 컬렉션 내부의 요소 타입을 지정 (attachedFile 타입의 객체가 리스트에 포함됨)
ㄴ <id> 태그:
     => column: 데이터베이스 컬럼의 이름을 지정 ("board_file_no" 컬럼을 사용하여 AttachedFile 객체의 no 프로퍼티에 매핑함)
     => property: 매핑 결과를 저장할 객체의 프로퍼티 이름을 지정 (no 프로퍼티에 매핑 결과를 저장)
ㄴ <result> 태그:
     => column: 데이터베이스 컬럼의 이름을 지정 ("filepath" 컬럼을 사용하여 AttachedFile 객체의 filePath 프로퍼티에 매핑)
     => property: 매핑 결과를 저장할 객체의 프로퍼티 이름을 지정 (filePath 프로퍼티에 매핑 결과를 저장)
=> 데이터베이스에서 조회된 결과를 attachedFiles 리스트의 각 AttachedFile 객체에 매핑하여 저장하도록 함

      ㄴ MyBatis는 이러한 설정을 통해 객체와 데이터베이스 간의 매핑을 유연하게 처리할 수 있도록 해줌

 

BoardDetailServlet.java

=>

ㄴ 서버 Restart 해주기

=>

ㄴ [등록] 선택

=>

ㄴ 오류 발생

=>

BoardDao.xml

ㄴ b. 을 추가해주도록 함

=>

ㄴ 서버 Restart 해주기

=>

=>

=>

BoardDetailServlet.java

ㄴ 상세보기에서 이미지가 출력되도록 html 수정

=>

ㄴ 서버 Restart 해주기

=>

 

이미지 링크 출력

=>

ㄴ 정상적으로 출력됨을 확인

 

이미지 출력

BoardDetailServlet.java

=>

ㄴ 서버 Restart 해주기

=>

ㄴ 이미지 정상적으로 출력됨을 확인