1) 사이트 접속하여 fileupload 검색
https://mvnrepository.com/
2) Apache Commons FileUpload에서 1.4버전
3) pom.xml에 라이브러리 추가
4) root-context.xml 등록
<!-- 파일 업로드를 위한 MutipartResolver 구현체 CommonsMultipartResolver를 bean으로 등록 -> CommonsMultipartResolver를 bean으로 등록하면 multipart/form-data 형식으로 요청 시 input type="file" 태그를 자동적으로 인식하여 MultipartFile 객체로 반환하고 파일 외의 데이터(정수, 문자열 등의 텍스트 데이터)는 기존처럼 사용 가능 (MultipartRequest 필요 없음) --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="maxUploadSize" value="104857600"/> <property name="maxUploadSizePerFile" value="104857600"/> <property name="maxInMemorySize" value="104857600"/> </bean> <!-- 104857600 byte == 100MB 20971520 byte == 20MB maxUploadSize : 한 요청당 업로드가 허용되는 최대 용량을 바이트 단위로 설정. -1 은 제한이 없다는 뜻으로 이 프로퍼티를 지정하지 않을때 기본값. maxUploadSizePerFile : 한 파일당 업로드가 허용되는 최대 용량을 바이트 단위로 설정. -1 은 제한이 없다는 뜻으로 이 프로퍼티를 지정하지 않을때 기본값. maxInMemorySize : 디스크에 저장하지 않고 메모리에 유지하도록 허용하는 바이트 단위의 최대 용량을 설정. 사이즈가 이보다 클 경우 이 사이즈 이상의 데이터는 파일에 저장됩니다. 기본값은 10240 바이트. 임시 저장 공간, 디비에는 안들어가도 서버단에는 파일이 올라갈 수 있다. 그러면 메모리 낭비가 심함 그래서 성공할 때만 파일을 저장하게하는 것 임시 저장된 공간의 허용치를 넘어가면 자동으로 서버에 저장됨 -->
@PostMapping("/profile")
public String updateProfile(
@ModelAttribute("loginMember") Member loginMember,// session에 올라간 회원 정보
@RequestParam("uploadImage") MultipartFile uploadImage, // 업로드 파일
@RequestParam Map<String, Object> map, // 모든 파라미터를 저장
HttpServletRequest req, // 파일 저장 경로 탐색용
RedirectAttributes ra) throws IOException {
// 경로 작성하기
// 1) 웹 접근 경로 (/comm/resuources/images/memberProfile/)
String webPath = "/resources/images/memberProfile/";
// 2) 서버 저장 폴더 경로
// C:\workspace\07_framework\comm\src\main\webapp\resources\images\memberProfile
Strng folderPath = req.getSession().getServletContext().getRealPath(webPath);
// 경로 2개, 이미지, delete, 회원번호 map에 담기
// delete는 이미 맵에 들어가져 있는 상태
map.put("webPath", webPath);
map.put("folderPath", folderPath);
map.put("uploadImage", uploadImage);
map.put("memberNo", memberNo);
int result = service.updateProfile(map);
String message = null;
if(result > 0) {
message = "프로필 이미지가 변경되었습니다";
// DB - 세션 동기화
loginMember.setProfileImage((String)map.get("profileImage"));
} else {
message = "프로필 이미지 변경 실패";
}
ra.addFlashAttribute("message", message);
return "redirect:profile";
}
@Override
public int updateProfile(Map<String, Object> map) throws IOException {
// webPath, folderPath, uploadImage, delete, memberNo
// 자주 쓰는 값 변수 저장
MultipartFile uploadImage = (MultipartFile)map.get("uploadImage");
String delete = (String)map.get("delete"); // "0" (변경) / "1" (삭제)
// 프로필 이미지 삭제 여부를 확인해서
// 삭제가 아닌 경우 (== 새 이미지로 변경) -> 업로드된 파일명을 변경
// 삭제가 된 경우 -> NULL 값을 준비 (DB update)
String renameImage = null; // 변경된 파일명 저장
if(delete.equals("0")) { // 이미지가 변경된 경우
// 파일명 변경
// uploadImage.getOriginalFilename() : 원본 파일명
renameImage = Util.fileRename(uploadeImage.getOriginalFilename());
// 2023042815432.png
map.get("profileImage", map.get("webPath") + renameImage);
// /resources/images/memberProfile/2023042815432.png
} else {
map.put("profileImage", null);
}
// DAO를 호출해서 프로필 이미지 수정
int result = dao.updateProfile(map);
// DB 수정 성공 시 메모리에 임시 저장되어있는 파일을 서버에 저장
if(result > 0 && map.get("profileImage") != null) {
uploadImage.transferTo(new File(map.get("folderPath") + renameImage));
}
return result;
}
public int updateProfile(Map<String, Object> map) {
return sqlSession.update("mypageMapper.updateProfile", map);
}
<update id = "updateProfile">
UPDATE MEMBER_S SET
PROFILE_IMG = #{profileImage}
WHERE MEMBER_NO = ${memberNo}
</update>