아이콘을 클릭하면 프로필사진 수정페이지가 뜨게 하려고 한다.

 

 

nav.jsp

더보기
<%@page import="com.cos.blog.model.Users"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<%
	// 	Users principal = (Users) session.getAttribute("principal");
%>

<!DOCTYPE html>
<html lang="en">
<head>
<title>blog</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="/blog/css/styles.css" rel="stylesheet">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>

<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-bs4.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote-bs4.min.js"></script>

</head>
<body>
	<nav class="navbar navbar-expand-md bg-dark navbar-dark">
		<a class="navbar-brand" href="/blog/index.jsp">Blog</a>
		<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavbar">
			<span class="navbar-toggler-icon"></span>
		</button>

		<div class="justify-content-between collapse navbar-collapse" id="collapsibleNavbar">
			<ul class="navbar-nav">

				<c:choose>
					<c:when test="${empty sessionScope.principal}">

						<li class="nav-item"><a class="nav-link" href="/blog/user?cmd=login">로그인</a></li>
						<li class="nav-item"><a class="nav-link" href="/blog/user?cmd=join">회원가입</a></li>

					</c:when>

					<c:otherwise>

						<li class="nav-item"><a class="nav-link" href="/blog/board?cmd=write">글쓰기</a></li>
						<li class="nav-item"><a class="nav-link" href="/blog/user?cmd=update">회원정보</a></li>
						<li class="nav-item"><a class="nav-link" href="/blog/user?cmd=logout">로그아웃</a></li>

					</c:otherwise>
					
				</c:choose>

			</ul>

			<ul class="navbar-nav">

				<c:if test="${not empty sessionScope.principal}">
					<li class="nav-item">
					
						<a href="/blog/user?cmd=profileUpload"> 
						
							<img style="border-radius: 20px" onerror="this.src='/blog/image/userProfile.png'"
								src="${sessionScope.principal.userProfile}" width="40px" height="40px" />
						</a>
					</li>
				</c:if>

			</ul>

		</div>
	</nav>
	<br>

 

이미지를 클릭하면 이동하는 경로를 지정해준다.

 

UsersController.java

더보기
package com.cos.blog.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.cos.blog.action.Action;
import com.cos.blog.action.user.UsersJoinAction;
import com.cos.blog.action.user.UsersJoinProcAction;
import com.cos.blog.action.user.UsersLoginAction;
import com.cos.blog.action.user.UsersLoginProcAction;
import com.cos.blog.action.user.UsersLogoutAction;
import com.cos.blog.action.user.UsersProfileUploadAction;
import com.cos.blog.action.user.UsersProfileUploadProcAction;
import com.cos.blog.action.user.UsersUpdateAction;
import com.cos.blog.action.user.UsersUpdateProcAction;
import com.cos.blog.action.user.UsersUsernameCheckAction;

// http://localhost:8000/blog/user
@WebServlet("/user")
public class UsersController extends HttpServlet {
	private final static String TAG = "UsersController : ";
	private static final long serialVersionUID = 1L;

	public UsersController() {
		super();
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doProcess(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doProcess(request, response);
	}

	protected void doProcess(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// http://localhost:8000/blog/user?cmd=join
		String cmd = request.getParameter("cmd");
		System.out.println(TAG + "router : " + cmd);
		Action action = router(cmd);
		action.execute(request, response);
	}

	public Action router(String cmd) {
		if (cmd.equals("join")) {
			// 회원가입 페이지로 이동
			return new UsersJoinAction();
		} else if (cmd.equals("joinProc")) {
			// 회원가입을 진행 한 후 -> index.jsp로 이동
			return new UsersJoinProcAction();
		} else if (cmd.equals("update")) {
			// 회원 수정 페이지로 이동 (세션에 User 오브젝트를 가지고 있을 예정)
			return new UsersUpdateAction();
		} else if (cmd.equals("updateProc")) {
			// 회원 수정을 진행 한 후 -> index.jsp로 이동
			return new UsersUpdateProcAction();
		} else if (cmd.equals("delete")) {
			// 회원 삭제를 진행 한 후 -> 로그아웃을 하고 -> index.jsp로 이동
		} else if (cmd.equals("login")) {
			// 회원 로그인 페이지로 이동
			return new UsersLoginAction();
		} else if (cmd.equals("loginProc")) {
			// 회원 로그인을 수행한 후 -> 세션에 등록을 하고 -> index.jsp로 이동
			return new UsersLoginProcAction();
		} else if (cmd.equals("logout")) {
			// 회원 로그인을 수행한 후 -> 세션에 등록을 하고 -> index.jsp로 이동
			return new UsersLogoutAction();
		} else if (cmd.equals("usernameCheck")) {
			return new UsersUsernameCheckAction();
		} else if (cmd.equals("usernameCheck")) {
			return new UsersUsernameCheckAction();
		} else if (cmd.equals("profileUpload")) {
			return new UsersProfileUploadAction();
		} else if (cmd.equals("profileUploadProc")) {
			return new UsersProfileUploadProcAction();
		}

		return null;
	}

}

 

라우터에서 UsersProfileUploadAction 을 리턴한다

 

 

UsersUpdateAction.java

더보기
package com.cos.blog.action.user;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.cos.blog.action.Action;

public class UsersUpdateAction implements Action{

	@Override
	public void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		RequestDispatcher dis = request.getRequestDispatcher("user/update.jsp");
		dis.forward(request, response);
		
	}
	
}

페이지이동

 

 

profileUpload.jsp

더보기
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<%@include file="../include/nav.jsp"%>



<div class="container">
	<div class="d-flex justify-content-center">
		<form action="/blog/user?cmd=profileUploadProc" method="post" enctype="multipart/form-data">

			<div class="form-group">
				<img id="img__wrap" onerror="this.src='/blog/image/userProfile.png'" src="${sessionScope.principal.userProfile}" width="350px" height="300px" />
			</div>
			<div class="form-group">
				<input type="file" name="userProfile" id="img__preview" />
				<!-- 단어를 이을 때 자바는 카멜 , html은 언더바를 주로 사용한다, 아이디쓸 때 언더바 두개 쓰기 -->
			</div>
				<input type="hidden" name="id" value="${sessionScope.principal.id}">
			<div class="form-group">
			
				<button class="btn btn-primary w-100">사진전송</button>
			
			</div>

		</form>
	</div>
</div>

<script src="/blog/js/imgPreview.js"></script>

<%@include file="../include/footer.jsp"%>

 

src를 세션의 principal에서 가져오고 만약에 null이거나 빈값이라면 onerror주소의 이미지를 가져온다

 

 

기본상태의 모습

 

 

파일을 선택 했을 때의 모습

 

 

imgPreview.js

더보기
$("#img__preview").on("change", (e) => {
	var f = e.target.files[0];
	
	console.log(f);

	if(!f.type.match("image*")){
		alert("이미지만 첨부 가능합니다.");
		$("#img__preview").val(""); // 이미지 파일이 아닐 경우 선택된 파일 없음 유지
		return;
	}

	if(f.size > 1024*1024*2){
		alert("용량을 초과 하였습니다.");
		$("#img__preview").val(""); // 이미지 파일이 아닐 경우 선택된 파일 없음 유지
		return;
	}
	
	var reader = new FileReader();
	
	// readAsDataURL(f)보다 위에 설정

	reader.onload = function (e) { // readAsDataURL(f)보다 아래에 있으면 타이밍이 안맞을 수 있음.
		$("#img__wrap").attr("src", e.target.result);			
	}
	
	reader.readAsDataURL(f); // 비동기 실행

	// reader.readAsDataURL(f); 가 실행이 끝나면 e.target(이벤트객체)에 result라는 객체를 하나
	// 생성하고 안에 이미지를 넣어준다.
	// $("#img__wrap").attr("src", e.target.result); // reader가 다읽으면 result가
	// 생성된다.(비동기이기때문에 작동안될 것)

});

 

이미지가 아니거나 용량을 초과 했을 경우 처리

 

이미지가 아닌 것을 올렸을 경우 메시지

 

 

reader객체를 선언하여 파일을 읽어오려고한다.

reader.readAsDataURL(f)를 이용하여 데이터를 먼저 받아오지 않고,

reader.onload를 먼저 선언해줘야한다.

reader.readAsDataURL(f)를 이용하여 데이터를 받아오면 자동으로 reader.onload()가 실행되는데,

너무 빨리 받아오면 onload함수를 선언하기도 전에 onload가 실행되기 때문에

미리 onload를 선언하고 데이터를 받아오게 한다.

데이터를 받아오면 target안에 result가 생성되고 result값을 이미지 미리보기의 주소값으로 바꾼다.

 

 

UsersProfileUploadProcAction.java

더보기
package com.cos.blog.action.user;

import java.io.BufferedReader;
import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.cos.blog.action.Action;
import com.cos.blog.model.Users;
import com.cos.blog.repository.UsersRepository;
import com.cos.blog.util.Script;
import com.oreilly.servlet.MultipartRequest;
import com.oreilly.servlet.multipart.DefaultFileRenamePolicy;

public class UsersProfileUploadProcAction implements Action {

	@Override
	public void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		// getServletContext()는 프로젝트가 여러개일 때 무조건 넣어줘야함
		String realPath = request.getServletContext().getRealPath("image");
		int id;
		String fileName = null;
		String contextPath = request.getServletContext().getContextPath();
		String userProfile = null; // DB에 들어갈 변수 : 위치
		
		
		System.out.println("real " + realPath);
		System.out.println("context " + contextPath);
		
		try {
			MultipartRequest multi = new MultipartRequest(request, realPath, 1024*1024*2, "utf-8", new DefaultFileRenamePolicy());
			
			fileName = multi.getFilesystemName("userProfile");
			
			System.out.println("fileName " + fileName);
			
			id = Integer.parseInt(multi.getParameter("id"));
			
			userProfile = contextPath + "/image/" + fileName;
			
			UsersRepository usersRepository = UsersRepository.getInstance();
			
			int result = usersRepository.update(id, userProfile);
			
			if(result == 1) {
				
				HttpSession session = request.getSession();
				Users principal = usersRepository.findById(id);
				session.setAttribute("principal", principal);
				
				Script.href("사진변경 완료", "/blog/index.jsp", response);
			} else {
				Script.back("사진 변경 실패", response);
			}
			
		} catch (Exception e) {
			e.getStackTrace();
		}
		
		
		
		
		
		
//		BufferedReader br = request.getReader();
//		StringBuilder sb = new StringBuilder();
//		
//		String input = null;
//		
//		while ((input = br.readLine()) != null) {
//			sb.append(input);
//		}
//		
//		System.out.println("사진받았음");
//		System.out.println(sb.toString());
//		Script.outText("테스트 중", response);
		
	}

}

 

realPath는 톰캣이 운영하는 진짜 주소를 말한다.

 

 

multipart/form-data타입으로 전송할경우 request로는 파일을 가져올 수 없다.

MultipartRequest클래스를 이용하여

request와 실제 저장할 경로, 최대 받을 용량, 캐릭터셋, 파일이름이 중복될 경우 사용할 정책을 설정한다.

 

유저 프로필 주소를 context주소를 기준으로 폴더 + 파일명을 붙여준다.

 

유저프로필 주소를 업데이트 한다.

 

쿼리 결과값이 1이면 세션을 다시 세팅해준다.

 

UsersRepository.java

더보기
package com.cos.blog.repository;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.cos.blog.db.DBConn;
import com.cos.blog.model.Users;

public class UsersRepository {
	private static final String TAG = "UserRepository : "; // TAG 생성 (오류 발견시 용이)
	private static UsersRepository instance = new UsersRepository();

	private UsersRepository() {
	}

	public static UsersRepository getInstance() {
		return instance;
	}

	private Connection conn = null;
	private PreparedStatement pstmt = null;
	private ResultSet rs = null;

	public int findByUsername(String username) {
		final String SQL = "SELECT count(*) " + "FROM users WHERE username=?";
		Users user = null;
		try {
			conn = DBConn.getConnection(); // DB에 연결
			pstmt = conn.prepareStatement(SQL);

			// 물음표 완성하기
			pstmt.setString(1, username);

			// if 돌려서 rs -> java오브젝트에 집어넣기
			rs = pstmt.executeQuery();

			if (rs.next()) {
				return rs.getInt(1);
			}

		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println(TAG + "findByUsername : " + e.getMessage());
		} finally {
			DBConn.close(conn, pstmt, rs);
		}

		return -1; // 실패시
	}
	

	public Users findByUsernameAndPassword(String username, String password) {
		final String SQL = "SELECT id, username, email, address, userProfile, userRole, createDate "
				+ "FROM users WHERE username=? AND password=?";
		Users user = null;
		try {
			conn = DBConn.getConnection(); // DB에 연결
			pstmt = conn.prepareStatement(SQL);

			// 물음표 완성하기
			pstmt.setString(1, username);
			pstmt.setString(2, password);

			// if 돌려서 rs -> java오브젝트에 집어넣기
			rs = pstmt.executeQuery();
			if (rs.next()) {
				user = new Users(); // 무조건 null이 아니라는 의미
				user.setId(rs.getInt("id"));
				user.setUsername(rs.getString("username"));
				user.setEmail(rs.getString("email"));
				user.setAddress(rs.getString("address"));
				user.setUserProfile(rs.getString("userProfile"));
				user.setUserRole(rs.getString("userRole"));
				user.setCreateDate(rs.getTimestamp("createDate"));
			}
			return user;
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println(TAG + "findByUsernameAndPassword : " + e.getMessage());
		} finally {
			DBConn.close(conn, pstmt, rs);
		}
		return null; // 실패시
	}

	// 회원가입
	public int save(Users user) { // object 받기(안에 내용 다 받아야 하니까) // insert하고 싶으면 save
		final String SQL = "INSERT INTO users(id, username, password, email, address, userRole, createDate) "
				+ "VALUES(USERS_SEQ.nextval,?,?,?,?,?,sysdate)"; // userProfile은 나중에 update
		try {
			conn = DBConn.getConnection(); // DB에 연결
			pstmt = conn.prepareStatement(SQL);
			// 물음표 완성하기

			pstmt.setString(1, user.getUsername());
			pstmt.setString(2, user.getPassword());
			pstmt.setString(3, user.getEmail());
			pstmt.setString(4, user.getAddress());
			pstmt.setString(5, user.getUserRole()); // user권한 (종류는 user, admin)

			return pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println(TAG + "save : " + e.getMessage());
		} finally {
			DBConn.close(conn, pstmt, rs);
		}
		return -1; // 실패시
	}

	// 회원정보 수정
	public int update(Users user) { // object 받기(안에 내용 다 받아야 하니까)
		final String SQL = "UPDATE users SET password = ?, email = ?, address = ? WHERE id = ? ";
		try {
			conn = DBConn.getConnection(); // DB에 연결
			pstmt = conn.prepareStatement(SQL);
			// 물음표 완성하기
		
			pstmt.setString(1, user.getPassword());
			pstmt.setString(2, user.getEmail());
			pstmt.setString(3, user.getAddress());
			pstmt.setInt(4, user.getId());
			
			return pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println(TAG + "update : " + e.getMessage());
		} finally {
			DBConn.close(conn, pstmt, rs);
		}
		return -1; // 실패시
	}
	
	// 회원정보 수정
	public int update(int id, String userProfile) {
		final String SQL = "UPDATE users SET userProfile = ? WHERE id = ? ";
		try {
			conn = DBConn.getConnection(); // DB에 연결
			pstmt = conn.prepareStatement(SQL);
			// 물음표 완성하기
		
			pstmt.setString(1, userProfile);
			pstmt.setInt(2, id);
			
			return pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println(TAG + "update : " + e.getMessage());
		} finally {
			DBConn.close(conn, pstmt, rs);
		}
		return -1; // 실패시
	}

	// 회원정보 삭제
	public int deleteById(int id) { // object 받기(안에 내용 다 받아야 하니까)
		final String SQL = "";
		try {
			conn = DBConn.getConnection(); // DB에 연결
			pstmt = conn.prepareStatement(SQL);
			// 물음표 완성하기
			return pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println(TAG + "Delete : " + e.getMessage());
		} finally {
			DBConn.close(conn, pstmt, rs);
		}
		return -1; // 실패시
	}

	// 회원정보 다 찾기
	public List<Users> findAll() { // object 받기(안에 내용 다 받아야 하니까)
		final String SQL = "";
		List<Users> users = new ArrayList<>();
		try {
			conn = DBConn.getConnection(); // DB에 연결
			pstmt = conn.prepareStatement(SQL);
			// 물음표 완성하기

			// while 돌려서 rs -> java오브젝트에 집어넣기
			return users;
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println(TAG + "findAll : " + e.getMessage());
		} finally {
			DBConn.close(conn, pstmt, rs);
		}
		return null; // 실패시
	}

	// 회원정보 한 건 찾기
	public Users findById(int id) { // object 받기(안에 내용 다 받아야 하니까)
		final String SQL = "SELECT id, username, email, address, userProfile, userRole, createDate "
				+ "FROM users WHERE id = ?";
		Users user = new Users();
		try {
			conn = DBConn.getConnection(); // DB에 연결
			pstmt = conn.prepareStatement(SQL);
			
			// 물음표 완성하기
			pstmt.setInt(1, id);
			
			rs = pstmt.executeQuery();
			

			// if 돌려서 rs -> java오브젝트에 집어넣기
			if(rs.next()) {
				
				user = new Users(); // 무조건 null이 아니라는 의미
				user.setId(rs.getInt("id"));
				user.setUsername(rs.getString("username"));
				user.setEmail(rs.getString("email"));
				user.setAddress(rs.getString("address"));
				user.setUserProfile(rs.getString("userProfile"));
				user.setUserRole(rs.getString("userRole"));
				user.setCreateDate(rs.getTimestamp("createDate"));
				
			}
			
			return user;
		} catch (SQLException e) {
			e.printStackTrace();
			System.out.println(TAG + "findById : " + e.getMessage());
		} finally {
			DBConn.close(conn, pstmt, rs);
		}
		return null; // 실패시
	}
}

 

기존의 update를 오버로딩하여 프로필만 업데이트 하는 쿼리를 실행한다.

 

결과

사진이 업로드 된 모습

'Web > Jsp' 카테고리의 다른 글

블로그 댓글쓰기  (0) 2020.06.12
블로그 댓글보기  (0) 2020.06.12
자바스크립트 on 이벤트  (0) 2020.06.11
multipart/form-data // HTML 파일업로드 MIME타입  (0) 2020.06.11
자바 UUID 생성  (0) 2020.06.11

+ Recent posts