반응형
파일 VO
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class FileVO {
private int fileNo;
private int boardNo;
private String filename;
private String filepath;
}
Board VO
import java.util.ArrayList;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Data
public class Board {
private int boardNo;
private String boardTitle;
private String boardContent;
private String boardWriter;
private String boardDate;
private ArrayList<FileVO> fileList; //DB에 전달하기 위해 Board VO 내에 생성
}
파일업로드 JSP
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>게시글작성(파일추가)</h1>
<hr>
<form action="/boardWrite2.do" method="post" enctype="multipart/form-data">
<fieldset>
제목 : <input type="text" name="boardTitle"><br>
첨부파일 : <input type="file" name="upfile" multiple><br>
내용 : <textarea rows="20" cols="50" name="boardContent"></textarea><br>
<input type="hidden" name="boardWriter" value="${sessionScope.m.memberId }">
<input type="submit" value="작성하기">
</fieldset>
</form>
</body>
</html>
파일 업로드를 위해 폼태그를 작성할때는 form에 method="post" , enctype="multipart/form-data" 를 반드시 적용해 주어야 한다.
파일 업로드 Controller
@RequestMapping("/boardWrite2.do")
public String boardWrite2(Board b, MultipartFile[] upfile, HttpServletRequest request) {
//파일 목록을 저장할 리스트 생성
ArrayList<FileVO> fileList = new ArrayList<FileVO>();
//MultipartFile 배열을 첨부파일의 갯수만큼 길이가 생성(단, 첨부파일이 없어도 길이는 무조건1)
//첨부파일이 없는 경우는 배열의 첫번째 파일이 비어있는지 체크하는 방식
if(upfile[0].isEmpty()) {
//사용하지 않지만 보여주기 위해 표현
//첨부파일이 없는 경우 수정할 로직이 없음
}else {
//첨부파일이 있는 경우 파일업로드 작업 진행
//1. 파일업로드 경로 설정 (HttpServletRequest 객체를 이용해서 경로를 구해옴)
// request.getSession().getServletContext() -> /webapp/ 까지의 경로
// .getRealPath("/resource/upload/board/") >> 추가 파일 경로
String savePath
= request.getSession().getServletContext().getRealPath("/resources/upload/board/");
//2. 반복문을 이용한 파일 업로드 처리
for(MultipartFile file : upfile) {
//파일명이 기존 파일과 겹치는 경우 기존파일을 삭제하고 새 파일만 남는 현상이 생김(덮어쓰기)
//파일명 중복인 경우 처리해줘야함
//사용자가 업로드한 파일 이름
String filename = file.getOriginalFilename();
//test.txt -> text_1.txt
//업로드한 파일명이 test.txt인 경우 -> text 와 .txt로 분리
//subString(포함 시작,미포함 끝)
//subString(미포함시작~끝까지)
String onlyFilename = filename.substring(0, filename.lastIndexOf(".")); //test
String extention = filename.substring(filename.lastIndexOf(".")); //.txt
//실제 업로드할 파일명 저장할 변수
String filepath = null;
//파일명 중복 시 뒤에 붙일 숫자 변수
int count = 0;
while(true) {
if(count == 0) {
//반복 첫번째 회차에는 원본 파일명을 그대로 적용
filepath = onlyFilename + extention; //test.txt
}else {
filepath = onlyFilename + "_" + count + extention;
}
//java.io 의 File
//파일 경로 + 파일이름으로 체크할 파일 생성
File checkFile = new File(savePath + filepath);
//체크파일명이 해당 경로에 존재하지 않으면 while문 break
if(!checkFile.exists()) {
break;
}
//파일명이 겹치지 않으면 count를 1씩 올려 다시 while문 실행
count++;
}//while문 end
//파일명 중복 검사가 끝난 시점 > 해당 파일 업로드
try {
//중복 처리가 끝난 파일명(filepath)으로 파일을 업로드할 FileOutputStream 객체 생성
FileOutputStream fos = new FileOutputStream(new File(savePath+filepath));
//업로드 속도 증가를 위한 보조스트림 생성
BufferedOutputStream bos = new BufferedOutputStream(fos);
//파일 업로드
byte[] bytes = file.getBytes();
bos.write(bytes);
bos.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//서버 파일업로드 작업 끝(파일 1개 단위)
//DB에 파일 정보 저장
FileVO fileVO = new FileVO();
fileVO.setFilename(filename); //업로드한 실제 파일 이름
fileVO.setFilepath(filepath); //서버에 저장될 이름
fileList.add(fileVO);
}//for문 end
}//else end
int result = service.insertBoard(b,fileList);
//성공 실패 결과 비교, fileList.size() == result 인 경우 insert 성공
return "redirect:/boardList.do";
}
파일 업로드 Service
public int insertBoard(Board b, ArrayList<FileVO> fileList) {
//board테이블에 게시글 작성
int result1 = dao.insertBoard(b);
int result = 0;
if(result1>0) {
//방금 작성한 게시글이 가장 최근에 작성한 게시글이기 때문에 boardNo값이 가장 큼 따라서 쿼리문은 max(board_no)로 작성
int boardNo = dao.selectBoardNo();
for(FileVO file : fileList) {
//mybatis에서 selectkey를 사용할 경우 b객체에 boardNo값이 담겨온다
//file.setBoardNo(b.getBoardNo());
file.setBoardNo(boardNo);
result += dao.insertFile(file);
}//for문 end
}else {
result = -1;
}//if문 end
return result;
}
게시글과 파일을 각각 데이터베이스에 따로 넣어주어야 함.
파일 업로드 mybatis DB 쿼리
<?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="boardDao">
<insert id="insertBoard" parameterType="board">
insert into board
values(board_seq.nextval, #{boardTitle}, #{boardContent}, #{boardWriter}, to_char(sysdate, 'yyyy-mm-dd'))
<!-- insert를 하고 난 후(order="AFTER")의 결과를 boardNo(keyProperty="boardNo", parameterType="board" /
return이 아니라 객체)에 넣어주고 아래의 sql문 실행-->
<selectKey resultType="int" order="AFTER" keyProperty="boardNo">
select max(board_no) from board
</selectKey>
</insert>
<select id="selectBoardNo" resultType="int">
select max(board_no) from board
</select>
<insert id="insertFile" parameterType="file">
insert into file_tbl values(file_seq.nextval, #{boardNo}, #{filename}, #{filepath})
</insert>
</mapper>
파일 다중 업로드시
@RequestMapping("admin_oneQuestion_replyOk.do")
public void admin_oneQuestionReplyOk(ServiceDTO serviceDto,
@RequestParam("page") int nowPage, HttpServletResponse response ,
@RequestParam("upfile")MultipartFile[] upfile) throws IOException {
System.out.println(serviceDto);
System.out.println(serviceDto.getService_group());
//service_num의 max값을 구해오는 메소드
//num = 원글의 group과 일치
int num = this.dao.getMaxServiceNum();
//group으로 step과 index의 max값을 가져옴
int step = this.dao.getStep(serviceDto.getService_group());
int indent = this.dao.getIndent(serviceDto.getService_group());
serviceDto.setService_indent(indent);
serviceDto.setService_step(step);
serviceDto.setService_num(num);
//답변등록
int check = this.dao.addOneQuestionReply(serviceDto);
//답변을 등록했으면 원글의 상태를 '답변완료'로 바꿔준다
this.dao.updateOneQuetionOrgingSi(num);
// fileDTO에 service_num의 fk 값을 주기위해 조회한다.
int sNum = this.dao.getServiceNumValue();
System.out.println("upfile.length///"+upfile.length);
//MultipartFile[] : 첨부파일의 갯수만큼 길이가 생성 (단, 첨부파일이 없어도 길이는 무조건 1)
//input이기 때문에 일단 데이터가 넘어오기 때문
//첨부파일이 없는 경우는 배열의 첫번째 파일이 비어있는지 체크하는 방식
//첨부파일이 있는 경우 파일 업로드 작업 진행
//1. 파일업로드 경로 설정(HttpServletRequest 객체를 이용해서 경로를 가져옴)
//request.getSession().getServletContext().getRealPath() -> /webapp/폴더경로
String savePath
= "C:\\Users\\ubg11\\ ~~~ \\src\\main\\webapp\\resources\\image_service\\upload\\";
//request.getSession().getServletContext().getRealPath("/resources/image_service/upload/");
//패스 경로 위에처럼 해야하는데 안돼서 직접 복사
//2. 반복문을 이용한 파일 업로드 처리
for(MultipartFile file : upfile) {
//넘어온 파일이 비어있을 경우 for문을 continue함 (실행하지 않고 빠져나가 다음 것을 실행함)
if(file ==null || file.isEmpty()) {continue;}
//파일명이 기존 파일과 겹치는 경우 기존 파일을 삭제하고 새 파일만 남는 현상이 생김(덮어쓰기)
//파일명 중복처리 (겹치면 넘버링 처리)
//사용자가 업로드한 파일 이름(원본파일이름)
String file_name = file.getOriginalFilename();
//test.txt 중복일 경우 -> test_1.txt -> test_2.txt
//업로드한 파일명이 test.txt인 경우 -> (test) (.txt) 두 부분으로 분리 (이름과 확장자로 분리)
//file_name.lastIndexOf(".") : file_name 중 0번째 자리부터 뒤에서 가장 가까운 인덱스 "." 까지 찾아 자른다.
String onlyFilename = file_name.substring(0, file_name.lastIndexOf(".")); // test
String extention = file_name.substring(file_name.lastIndexOf(".")); // .txt
//실제 업로드할 파일명을 저장할 변수
String file_path = null;
//파일명 중복시 뒤에 붙일 수자 변수
int count = 0;
//중복이 안될때까지 반복해야하기 때문에 무한반복 사용
while(true) {
if(count == 0) {
//반복 첫째회차에는 원본 파일명 그대로 적용
file_path = onlyFilename + extention; //test.txt
}else {
file_path = onlyFilename + "_" + count + extention; //test + _ + count값 + .txt
}
//저장경로에 들어가 파일과 같은 이름이 있는지 확인
File checkFile = new File(savePath+file_path);
if(!checkFile.exists()) { //.exists() : 존재여부 확인
//중복 파일명이 존재하지 않을때까지 반복후 존재하지 않으면 break로 while문을 나온다.
break;
}
count++;
}//파일명 중복 검사가 끝난 시점 -> 해당파일 업로드 작업
try {
//중복처리가 끝난 파일명(file_path)으로 파일을 업로드할 FileOutputStream 객체 생성
FileOutputStream fos = new FileOutputStream(new File(savePath+file_path));
//업로드 속도증가를 위한 보조 스트림 생성
BufferedOutputStream bos = new BufferedOutputStream(fos);
//파일업로드 처리
byte[] bytes = file.getBytes();
bos.write(bytes);
bos.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
//서버 파일 업로드 작업 끝(파일 1개 단위)
ServiceFileDTO fDto = new ServiceFileDTO();
fDto.setService_num(sNum);
fDto.setFile_name(file_name);
fDto.setFile_path(file_path);
//fileList.add(fDto);
//반복적으로 서버에 추가
this.dao.addFile(fDto);
}
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
if (check > 0) {
out.println("<script>");
out.println("alert('작성 완료')");
out.println("location.href='oneQuestion_list.do?page=" + nowPage + "'");
out.println("</script>");
} else {
out.println("<script>");
out.println("alert('작성 실패')");
out.println("history.back()");
out.println("</script>");
}
}
300x250
'개발자 > 자바 & 스프링' 카테고리의 다른 글
jQuery Ajax 방식 / Json / Gson (0) | 2023.02.19 |
---|---|
자바 스프링 파일 다운로드 / 이미지 다운로드 (0) | 2023.02.15 |
Spring, mybatis 페이징 처리 / 자바 스프링 페이징 (0) | 2023.02.14 |
MVC 아키텍쳐 / MVC1, MVC2 패턴 (0) | 2023.02.13 |
JSP 내장객체 (0) | 2023.02.13 |
댓글