결과 샷
1. 한글 이름의 파일은 미리보기가 불가능하고, 영어이름의 파일은 미리보기가 가능.
2. 다운로드는 당연히 모두다 가능
3. sqldeveloper에도 잘 올라가있음
1. pom.xml
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.8</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- 파일업로드를 위한 2개 디펜던시 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
2. root-context.xml
<!-- MyBatis용 3개 bean -->
<bean id= "dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@자신의 오라클주소" />
<property name="username" value="오라클계정" />
<property name="password" value="오라클비밀번호" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mapperLocations" value="classpath:com/koreait/mybatis02/dao/mapper/*.xml" />
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory"/>
</bean>
<!-- 파일업로드 : CommonsMultipartResolver -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="utf-8" />
<property name="maxUploadSize" value="10485760" /> <!-- 10MB = 1024 * 1024 * 10 -->
</bean>
3. mapper.xml
<mapper namespace="com.koreait.mybatis02.dao.ImageboardDao"> // 매퍼가 들어있는 위치
<insert id="imageboardInsert">
INSERT
INTO IMAGEBOARD
VALUES (IMAGEBOARD_SEQ.NEXTVAL, #{param1}, #{param2}, #{param3}, #{param4}, SYSDATE)
</insert>
<select id="imageboardList" resultType="com.koreait.mybatis02.dto.ImageboardDto">
SELECT *
FROM IMAGEBOARD
</select>
</mapper>
4. controller
5. Command
1) 리스트를 보여주는 커맨드
public class ImageboardListCommand implements ImageboardCommand {
@Override
public void execute(SqlSession sqlSession, Model model) {
ImageboardDao iDao = sqlSession.getMapper(ImageboardDao.class);
model.addAttribute("list", iDao.imageboardList());
}
}
2) 이미지를 업로드하는 커맨드
public class ImageboardInsertCommand implements ImageboardCommand {
@Override
public void execute(SqlSession sqlSession, Model model) {
// model -> map -> multipartRequest -> each parameter
Map<String, Object> map = model.asMap();
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) map.get("multipartRequest");
String writer = multipartRequest.getParameter("writer");
String title = multipartRequest.getParameter("title");
String content = multipartRequest.getParameter("content");
// if attached files are multiple, will save in List
// A type of attached files is MultipartFile
List<MultipartFile> fileList = multipartRequest.getFiles("files");
// checking whether attached files exists or not
if (fileList != null) {
// taking attachment file out from the list
for (MultipartFile file: fileList) {
// rechecking
if ( file != null && !file.isEmpty() ) {
// separate name/ file extension from original file
// 1) no duplicate file name
// 2) 업로드할 파일의 제한
String originalFilename= file.getOriginalFilename();
String extName = originalFilename.substring(originalFilename.lastIndexOf(".")+1); // file extension
String saveFilename = null;
try {
// to avoid duplicated filename : originalfilename_uploadtime.file
saveFilename = originalFilename.substring(0, originalFilename.lastIndexOf(".")) // original filename
+ "_" // _
+ System.currentTimeMillis() // upload time
+ "." // .
+ extName; // file extension
// to get the path attachment will be saved
String realPath = multipartRequest.getSession().getServletContext().getRealPath("/resources/storage");
// to create a new path if there is no realPath(/resources/storage) on server
File directory = new File(realPath);
if ( !directory.exists() ) {
directory.mkdirs();
}
// to create a saveFile
File saveFile = new File(realPath, saveFilename);
// to execute upload (save a file on server)
file.transferTo(saveFile);
// to save filename on DB
ImageboardDao iDao = sqlSession.getMapper(ImageboardDao.class);
iDao.imageboardInsert(writer, title, content, saveFilename);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
}
3) 다운로드이미지 커맨드
public class ImageboardDownloadCommand implements ImageboardCommand {
@Override
public void execute(SqlSession sqlSession, Model model) {
Map<String, Object> map = model.asMap();
HttpServletRequest request = (HttpServletRequest) map.get("request");
HttpServletResponse response = (HttpServletResponse) map.get("response");
String realPath = request.getServletContext().getRealPath("/resources/storage");
// 다운로드 파일 이름
// filename
// 업로드 할 때 파일 이름 : car.jpg
// 실제 저장된 파일 이름 : car_123456789.jpg
String filename = request.getParameter("filename");
// 확장자 분리
String extName = filename.substring(filename.lastIndexOf(".") + 1); // 확장자 extName
// 마지막 밑줄(_) 이전까지 파일명 분리
String downloadFilename = filename.substring(0, filename.lastIndexOf("_")) +
"." +
extName;
// 다운로드 할 파일 준비
File file = new File(realPath, filename);
// 입출력 스트림 준비
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
// 다운로드는 사용자에게 돌려주는 응답의 개념이므로,
// response 처리를 해야 한다.
response.setHeader("Content-Type", "application/x-msdownload");
response.setHeader("Content-Disposition", "attachment; filename=" + new String(URLEncoder.encode(downloadFilename, "utf-8")));
response.setHeader("Content-Length", file.length() + "");
// 입출력 스트림 생성
bis = new BufferedInputStream(new FileInputStream(file)); // 다운로드 할 파일을 읽는 스트림
bos = new BufferedOutputStream(response.getOutputStream()); // 사용자와 연결된(사용자에게 출력하는) 스트림
// 입력스트림 -> 출력스트림 : 복사
FileCopyUtils.copy(bis, bos);
// 혹시 남아 있는 출력스트림의 데이터 모두 보내기
bos.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (bos != null) { bos.close(); } // 입출력 스트림 닫아주기
if (bis != null) { bis.close(); }
} catch (Exception e) {
// TODO: handle exception
}
}
}
}
6. view (JSP)
jsp 로는 해당 컨트롤러로 이동하는 스크립트만 짜놨기 때문에 생략.
'Backend > Spring' 카테고리의 다른 글
6. STS / RESTful API 로 user 정보 관리하는 관리자페이지만들기 (0) | 2020.09.12 |
---|---|
5. STS / REST API (0) | 2020.09.07 |
3. STS 로 랜덤한 숫자의 인증코드 이메일로 보내고 인증절차 거치기 (0) | 2020.09.02 |
2. List/Set/Map handler (0) | 2020.08.20 |
1. Spring IoC / DI (0) | 2020.08.20 |