일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 로그인
- 이미지 업로드
- RCPS
- 빌드 및 배포
- mypage
- 공통메서드
- 밸류즈
- 달력 라이브러리
- userManagement
- 캘린더 라이브러리
- register
- MRC
- 스프링시큐리티
- 회원가입로직
- 파생상품평가
- Token
- stock option
- 관리자페이지
- jsonwebtoken
- 마이페이지
- 배포
- 로그인 로직
- react
- 인증처리
- Ajax
- Update
- Typesciprt
- 밸류즈 홈페이지
- ui탬플릿
- Styled Components
- Today
- Total
I T H
[스프링프로젝트연습 18] 스프링 프로젝트 구현 - 관리자페이지: 이미지 업로드 본문
관리자 페이지용으로 단일 이미지 업로드 테스트를 위한 페이지를 구현하고자 한다.
[ 테이블 생성 ]
프로필 정보를 저장하기 위한 데이터베이스 테이블을 1개 생성한다.
CREATE TABLE TBL_PROFILE_INFO (
PROFILE_ID varchar(10) NOT NULL PRIMARY KEY,
PROFILE_NAME varchar(20) NOT NULL,
PROFILE_JOB varchar(100) NOT NULL,
PROFILE_EMAIL varchar(100) DEFAULT NULL,
PROFILE_IMG varchar(100) DEFAULT NULL
)
[ Dependency 추가 ]
파일 업로드를 위한 라이브러리를 참조하기 위해 pom.xml 파일에 아래 내용을 추가한다.
참고 > https://commons.apache.org/proper/commons-fileupload/
FileUpload – Home
Commons FileUpload The Commons FileUpload package makes it easy to add robust, high-performance, file upload capability to your servlets and web applications. FileUpload parses HTTP requests which conform to RFC 1867, "Form-based File Upload in HTML". That
commons.apache.org
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
[ JavaConfig 설정 ]
- kr.co.values.init 패키지 아래에 클래스 파일 내용을 수정한다.
- multipartResolver 빈 등록
package kr.co.values.init;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
/**
* servlet-context.xml 파일을 대신하는 클래스
* @ComponentScan 을 통하여 컨트롤러 클래스가 존재하는 패키지를 자동 스캔한다.
*/
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "kr.co.values.web" } )
public class ServletConfig implements WebMvcConfigurer {
private final int MAX_SIZE = 10 * 1024 * 1024;
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setViewClass(JstlView.class);
bean.setPrefix("/WEB-INF/views/");
bean.setSuffix(".jsp");
registry.viewResolver(bean);
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
@Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(MAX_SIZE); // 10MB
multipartResolver.setMaxUploadSizePerFile(MAX_SIZE); // 10MB
multipartResolver.setMaxInMemorySize(0);
return multipartResolver;
}
}
다음으로는 관리자용 페이지를 하나 생성한다. JSP~컨트롤러까지 admin 이라는 이름으로 한 세트를 작성한다.
[ JSP ]
webapp/WEB-INF/views/main/admin.jsp 파일 생성한다.
파일 1개에 대한 이미지 업로드를 진행하기 위해 file 태그가 포함된 구문을 작성한다.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.0.js"></script>
</head>
<body>
<p>ADMIN PAGE</p>
<label>프로필 이미지</label>
<input id="file" name="file" type="file" style="padding: 5pt;">
<label>프로필 이름</label>
<input type="text" id="profileName">
<label>프로필 직업</label>
<input type="text" id="profileJob">
<label>프로필 이메일</label>
<input type="text" id="profileEmail">
<button id="btnRegister">프로필 등록</button>
<script src="/resources/ajax.js"></script>
<script src="/resources/admin.js"></script>
</body>
</html>
[ 이벤트 처리 ]
resources / admin.js 내에 스크립트를 작성한다.
스크립트 내용은 아래와 같다.
- 프로필 정보를 저장할 때 이미지를 등록한 경우에는 이미지(파일) 업로드를 먼저 진행한다.
- 반대로 이미지가 등록되지 않은 경우에는 정보 업데이트만 진행한다.
$(function(){
$("#btnRegister").on("click", function(){
var profileName = $("#profileName").val();
var profileJob = $("#profileJob").val();
var profileEmail = $("#profileEmail").val();
if(profileName == null || profileName == ""){
alert("프로필 이름을 입력하세요.");
return;
}
obj = {
profileName: profileName,
profileJob: profileJob,
profileEmail: profileEmail,
profileImg: ""
}
// 프로필 저장 시에는 아래와 같은 순서로 처리한다.
// 1. 프로필 이미지를 포함하여 등록 버튼을 누른 경우에는 이미지를 먼저 업로드하고 (업로트 컨트롤러 호출) 저장된 이미지명을 전달받은 후
// 전달받은 이미지명을 파라미터에 포함한 뒤프로필 정보를 저장한다.
// 서버사이드에서는 프로필 정보가 이미 저장되어 있는지 체크 후 insert 혹은 update로 프로플 정보를 저장하게 된다.
var fileImg = $("#file").val();
if(fileImg == null || fileImg == ""){ //이미지가 포함되지 않은경우
dataSaveAjax("/admin/updateProfile.do", obj, "POST");
} else { //이미지 포함된 경우
var ext = $("#file").val().split('.').pop().toLowerCase(); // ex) ~.txt -> txt
if($.inArray(ext, ['gif', 'png', 'jpg', 'jpeg'] == -1)){
alert('gif, png, jpg, jpeg 파일만 업로드 할수 있습니다.');
return false;
}
var formData = new FormData();
formData.append("file", $("#file")[0].files[0]); //파일 한개
formData.append("params", JSON.stringify(obj));
formData.append("enctype", "multipart/form-data");
$.ajax({
url: "/admin/profileUpload.do",
type: "POST",
processData: false, //file전송시 필수
contentType: false, //file전송시 필수
data: formData,
dataType: "json",
success: function(data){
// 이미지 등록이 완료되면 서버 사이드에서 전달해주는 src 키에 매핑된 파일명 값을 obj 파라미터에 담은 후
// 프로필 정보를 저장하는 컨트롤러를 호출한다
console.log("data", data);
obj.profileImg = data.src;
dataSaveAjax("/admin/updateProfile.do", obj, "POST");
}
});
}
})
})
[ 컨트롤러 구현 ]
kr\co\values\web\AdminController.java 파일을 생성하여 아래 내용을 입력한다.
<참고>
transferTo() : 파일을 저장한다
getOriginalFilename() : 파일 이름을 String 값으로 반환한다
getSize() : 파일 크기를 반환한다
getInputStream() : 파일에 대한 입력 스트림을 얻어온다
package kr.co.values.web;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.fileupload.FileUploadException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import kr.co.values.service.AdminService;
@Controller
public class AdminController {
@Autowired
private AdminService adminService;
@RequestMapping("/admin/main.do")
public String main() {
return "main/admin";
}
// 프로필 정보 저장
@RequestMapping("/admin/updateProfile.do")
@ResponseBody
public Map<String, Object> updateProfile(@RequestBody Map<String, Object> params) {
adminService.updateProfile(params);
Map<String, Object> result = new HashMap<String, Object>();
result.put("result", true);
return result;
}
/**
* 업로드 (프로필 이미지 파일 업로드)
* for Servlet2.5 Multipart FileUpload
* @throws FileUploadException
*/
@RequestMapping("/admin/profileUpload.do")
@ResponseBody
public Map<String, Object> profileUpload(@RequestParam("file") MultipartFile part, HttpServletRequest request) throws FileUploadException {
ServletContext context = request.getSession().getServletContext();
String path = context.getRealPath("/resources/images/profile");
System.out.println("path : " + path);
String fileName = part.getOriginalFilename();
System.out.println("fileName : " + fileName);
InputStream in = null;
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
Date time = new Date();
String forTime = format.format(time);
int pos = fileName.lastIndexOf(".");
String ext = fileName.substring(pos + 1);
try {
File f = new File(path + "/" + forTime + "." + ext);
part.transferTo(f);
} catch (Exception e) {
throw new FileUploadException(); // 파일업로드를 실패하였습니다.
} finally {
if (in != null)
try {
in.close();
} catch (IOException e) {
}
}
Map<String, Object> result = new HashMap<String, Object>();
result.put("src", forTime + "." + ext); // 현재시간으로 변경된 파일명을 화면 뷰로 전달해준다. 이 파일명을 데이터베이스 테이블에 저장하게 된다.
return result;
}
}
[ 서비스 구현 ]
kr\co\values\service\AdminService.java 파일을 생성한다.
package kr.co.values.service;
import java.util.Map;
public interface AdminService {
// 프로필 정보 저장
void updateProfile(Map<String, Object> map);
}
서비스 단에서 이미 저장된 프로필 정보가 있는 경우를 체크하여 없으면 insert를 진행하고
반대라면 update를 진행하게 되도록 로직을 구현한다.
kr\co\values\service\AdminServiceImpl.java 파일을 생성한다.
package kr.co.values.service;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import kr.co.values.persistence.AdminMapper;
@Service
public class AdminServiceImpl implements AdminService {
@Autowired
private AdminMapper adminMapper;
@Override
public void updateProfile(Map<String, Object> map) {
// 1. 프로필 정보를 저장하기 전에 프로필 테이블에 이미 저장된 정보가 있는지 체크한다.
List<Map<String, Object>> list = adminMapper.searchProfile(map);
if(list.size() > 0) { // 정보가 있는 경우에는 업데이트로 프로필 정보를 변경
map.put("profileId", list.get(0).get("PROFILE_ID"));
adminMapper.updateProfile(map);
}
else { // 정보가 없는 경우에는 인서트로 프로필 정보를 최초 저장
adminMapper.insertProfile(map);
}
}
}
[ 매퍼 구현 ]
kr\co\values\persistence\AdminMapper.java 파일을 생성한다.
package kr.co.values.persistence;
import java.util.List;
import java.util.Map;
public interface AdminMapper {
// 프로필 저장 정보 조회
public List<Map<String, Object>> searchProfile(Map<String, Object> map);
// 프로필 정보 저장
public void insertProfile(Map<String, Object> map);
// 프로필 정보 업데이트
public void updateProfile(Map<String, Object> map);
}
kr\co\values\persistence\AdminMapper.xml 파일을 생성한다.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="kr.co.values.persistence.AdminMapper">
<!-- 프로필 정보 조회 -->
<select id="searchProfile" parameterType="hashmap" resultType="hashmap">
SELECT *
FROM TBL_PROFILE_INFO
WHERE 1=1
</select>
<!-- 프로필 최초 저장 -->
<insert id="insertProfile" parameterType="hashmap">
INSERT INTO TBL_PROFILE_INFO (
PROFILE_ID
, PROFILE_NAME
, PROFILE_JOB
, PROFILE_EMAIL
, PROFILE_IMG
)
VALUES (
'profile' /* 아이디는 고정하여 사용 */
, #{profileName}
, #{profileJob}
, #{profileEmail}
, #{profileImg}
)
</insert>
<!-- 프로필 정보 업데이트 -->
<update id="updateProfile" parameterType="hashmap">
UPDATE TBL_PROFILE_INFO
SET PROFILE_NAME = #{profileName}
, PROFILE_JOB = #{profileJob}
, PROFILE_EMAIL = #{profileEmail}
, PROFILE_IMG = #{profileImg}
WHERE PROFILE_ID = #{profileId}
</update>
</mapper>
[ 실행 결과 ] - /admin/main.do 페이지로 접속 후 기능 테스트

'Spring Basic' 카테고리의 다른 글
[Spring Boot] 1. 계획 수립 / Spring Boot 시작하기 (Week 1) (0) | 2024.01.24 |
---|---|
[스프링프로젝트연습 19] 스프링 프로젝트 구현 - Spring Security (0) | 2024.01.22 |
[스프링프로젝트연습 17] 스프링 프로젝트 구현 - Junit 테스트 (0) | 2024.01.22 |
[스프링프로젝트연습 16] 스프링 프로젝트 구현 - CRUD 서비스 로직 추가 (0) | 2024.01.22 |
[스프링프로젝트연습 15] 스프링 프로젝트 구현 - 트랜잭션 처리 (0) | 2024.01.22 |