κ²μν - νμΌ μ λ‘λ
μ€ν μ’ λλ¬μ£ΌμΈμ
Spring Boot (Back-End)
Spring Boot λ‘ νμΌ μ
λ‘λ, μ‘°ν, μμ κΈ°λ₯μ ꡬνν©λλ€.
ꡬν κΈ°λ₯
β’
νμΌ μ
λ‘λ
β¦
λ°μ΄ν°λ² μ΄μ€μ λ±λ‘
β¦
νμΌ μμ€ν
μ λ±λ‘
β’
οΈ νμΌ μ‘°ν
β¦
νμΌ λͺ©λ‘ μ‘°ν
β¦
λ€μ΄λ‘λ
β¦
μΈλ€μΌ μ΄λ―Έμ§ 보기
β’
νμΌ μμ
β¦
κ²μκΈμ μ’
μλ μ¬λ¬ νμΌ μμ
β¦
μ ν νμΌ μμ
β¦
κ°λ³ νμΌ μμ
React (Front-End)
React λ‘ νμΌ μ
λ‘λ, μ‘°ν, μμ UI λ° API λ₯Ό ꡬνν©λλ€.
β’
νμΌ μ
λ‘λ
β¦
νμΌ λ±λ‘ UI μΆκ°
β¦
νμΌ μ
λ‘λ μμ² API
β’
οΈ νμΌ μ‘°ν
β¦
νμΌ λͺ©λ‘ μ‘°ν UI λ° API μΆκ°
β¦
λ€μ΄λ‘λ UI λ° API μΆκ°
β¦
μΈλ€μΌ μ΄λ―Έμ§ UI μΆκ°
β’
νμΌ μμ
β¦
κ²μκΈμ μ’
μλ μ¬λ¬ νμΌ μμ (κ²μκΈ μμ μ, λ°±μλμμ μ²λ¦¬ν¨)
β¦
μμ ν νμΌ μ²΄ν¬λ°μ€ UI μΆκ° λ° μμ μμ² μ, μμ ν νμΌ λ²νΈ 리μ€νΈ λ°μ΄ν° μΆκ°
β¦
κ°λ³ νμΌ μμ UI λ° API μΆκ°
Spring Boot (Back-End)
Spring Boot λ‘ νμΌ μ
λ‘λ, μ‘°ν, μμ κΈ°λ₯μ ꡬνν©λλ€.
νμΌ μ λ‘λ
λ°μ΄ν°λ² μ΄μ€μ λ±λ‘
1.
λ°μ΄ν° λ² μ΄μ€ - ν
μ΄λΈ μμ±
2.
SQL 쿼리 Mapper μμ±
3.
DTO
4.
Mapper
5.
Service
6.
Controller
λ°μ΄ν° λ² μ΄μ€ - ν μ΄λΈ μμ±
CREATE TABLE `file` (
`no` int NOT NULL AUTO_INCREMENT, -- νμΌ λ²νΈ (μλμ¦κ°)
`parent_table` varchar(45) NOT NULL, -- λΆλͺ¨ ν
μ΄λΈλͺ
(μ: 'board')
`parent_no` int NOT NULL, -- λΆλͺ¨ ν
μ΄λΈμμμ λ²νΈ
`file_name` text NOT NULL, -- μ μ₯λ νμΌλͺ
`origin_name` text, -- μλ³Έ νμΌλͺ
`file_path` text NOT NULL, -- νμΌ κ²½λ‘
`file_size` int NOT NULL DEFAULT '0', -- νμΌ ν¬κΈ° (κΈ°λ³Έκ° 0)
`reg_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, -- λ±λ‘μΌμ
`upd_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, -- μμ μΌμ
`file_code` int NOT NULL DEFAULT '0', -- νμΌ μ½λ (κΈ°λ³Έκ° 0)
PRIMARY KEY (`no`) -- μ£Όν€ μ€μ
) COMMENT='νμΌ';
SQL
볡μ¬
SQL 쿼리 Mapper μμ±
β’
FileMapper.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">
<!-- namespace="λ§€νΌ μΈν°νμ΄μ€ κ²½λ‘" -->
<mapper namespace="com.joeun.server.mapper.FileMapper">
<!-- νμΌ λͺ©λ‘ -->
<select id="list" resultType="Files">
SELECT *
FROM file
ORDER BY reg_date DESC
</select>
<!-- νμΌ λͺ©λ‘ - λΆλͺ¨ ν
μ΄λΈ κΈ°μ€ -->
<!-- * νμΌμ΄ μ’
μλλ ν
μ΄λΈμ κΈ°μ€μΌλ‘ νμΌ λͺ©λ‘μ μ‘°ν -->
<!-- * κ²μκΈ λ²νΈ 10
π νμΌ λ²νΈ 1
π νμΌ λ²νΈ 2
π νμΌ λ²νΈ 3
-->
<select id="listByParent" resultType="Files">
SELECT *
FROM file
WHERE parent_table = #{parentTable}
AND parent_no = #{parentNo}
ORDER BY reg_date DESC
</select>
<!-- νμΌ μ‘°ν -->
<select id="select" resultType="Files">
SELECT *
FROM file
WHERE no = #{no}
</select>
<!-- νμΌ λ±λ‘ -->
<insert id="insert">
INSERT INTO file( parent_table, parent_no, file_name, origin_name, file_path, file_size, file_code )
VALUES ( #{parentTable}, #{parentNo}, #{fileName}, #{originName}, #{filePath}, #{fileSize}, #{fileCode} )
</insert>
<!-- νμΌ μμ -->
<update id="update">
UPDATE file
SET parent_table = #{parentTable}
,parent_no = #{parentNo}
,file_name = #{fileName}
,origin_name = #{originName}
,file_path = #{filePath}
,file_size = #{fileSize}
,file_code = #{fileCode}
WHERE no = #{no}
</update>
<!-- νμΌ μμ -->
<delete id="delete">
DELETE FROM file
WHERE no = #{no}
</delete>
<!-- νμΌ λͺ©λ‘ μμ - λΆλͺ¨ ν
μ΄λΈ κΈ°μ€ νμΌ λͺ©λ‘ μμ -->
<delete id="deleteByParent">
DELETE FROM file
WHERE parent_table = #{parentTable}
AND parent_no = #{parentNo}
</delete>
<!-- κ²μκΈ λ²νΈ μ΅λκ° -->
<select id="maxPk" resultType="int">
SELECT MAX(no)
FROM file
</select>
</mapper>
SQL
볡μ¬
DTO
β’
Files.java
package com.joeun.server.dto;
import java.util.Date;
import lombok.Data;
@Data
public class Files {
private int no;
private String parentTable;
private int parentNo;
private String fileName;
private String originName;
private String filePath;
private long fileSize;
private Date regDate;
private Date updDate;
private int fileCode;
}
Java
볡μ¬
Mapper
β’
FileMapper.java
package com.joeun.server.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.joeun.server.dto.Files;
@Mapper
public interface FileMapper {
// νμΌ λͺ©λ‘
public List<Files> list() throws Exception;
// νμΌ μ‘°ν
public Files select(int no) throws Exception;
// νμΌ λ±λ‘
public int insert(Files file) throws Exception;
// νμΌ μμ
public int update(Files file) throws Exception;
// νμΌ μμ
public int delete(int no) throws Exception;
// νμΌ λ²νΈ(κΈ°λ³Έν€) μ΅λκ°
public int maxPk() throws Exception;
// νμΌ λͺ©λ‘ - λΆλͺ¨ κΈ°μ€
public List<Files> listByParent(Files file) throws Exception;
// νμΌ μμ - λΆλͺ¨ κΈ°μ€
public int deleteByParent(Files file) throws Exception;
}
Java
볡μ¬
Service
β’
FileService.java
β’
FileServiceImpl.java
β’
BoardServiceImpl.java
β’
FileService.java
package com.joeun.server.service;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import jakarta.servlet.http.HttpServletResponse;
public interface FileService {
// νμΌ λͺ©λ‘
public List<Files> list() throws Exception;
// νμΌ μ‘°ν
public Files select(int no) throws Exception;
// νμΌ λ±λ‘
public int insert(Files file) throws Exception;
// νμΌ μμ
public int update(Files file) throws Exception;
// νμΌ μ
λ‘λ
public int uploadFiles(Files file, List<MultipartFile> fileList) throws Exception;
// νμΌ μ
λ‘λ
public int upload(Files file) throws Exception;
}
Java
볡μ¬
β’
FileServiceImpl.java
package com.joeun.server.service;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.FileMapper;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class FileServiceImpl implements FileService {
@Autowired
private FileMapper fileMapper;
@Value("${upload.path}") // application.properties μ μ€μ ν μ
λ‘λ κ²½λ‘ μμ±λͺ
private String uploadPath; // μ
λ‘λ κ²½λ‘
@Override
public List<Files> list() throws Exception {
List<Files> fileList = fileMapper.list();
return fileList;
}
@Override
public Files select(int no) throws Exception {
Files file = fileMapper.select(no);
return file;
}
@Override
public int insert(Files file) throws Exception {
int result = fileMapper.insert(file);
return result;
}
@Override
public int update(Files file) throws Exception {
int result = fileMapper.update(file);
return result;
}
@Override
public int uploadFiles(Files fileInfo, List<MultipartFile> fileList) throws Exception {
int result = 0;
for (MultipartFile file : fileList) {
result += uploadFile( fileInfo, file );
}
log.info(result + "κ° νμΌμ μ
λ‘λνμμ΅λλ€.");
return result;
}
@Override
@Transactional
public int upload(Files file) throws Exception {
int result = uploadFile(file, file.getFile());
if( result > 0 )
result = fileMapper.maxPk();
return result;
}
public int uploadFile(Files fileInfo, MultipartFile file) throws Exception {
int result = 0;
if( file.isEmpty() ) return result;
// νμΌ μ 보 : μλ³ΈνμΌλͺ
, νμΌ μ©λ, νμΌ λ°μ΄ν°
String originName = file.getOriginalFilename();
long fileSize = file.getSize();
// μ
λ‘λ κ²½λ‘
// νμΌλͺ
μ€λ³΅ λ°©μ§ λ°©λ²(μ μ±
)
// - λ μ§_νμΌλͺ
.νμ₯μ
// - UID_νμΌλͺ
.νμ₯μ
// UID_κ°μμ§.png
String fileName = UUID.randomUUID().toString() + "_" + originName;
// c:/upload/UID_κ°μμ§.png
String filePath = uploadPath + "/" + fileName;
// - DB μ νμΌ μ 보 λ±λ‘
Files uploadedFile = new Files();
uploadedFile.setParentTable(fileInfo.getParentTable());
uploadedFile.setParentNo(fileInfo.getParentNo());
uploadedFile.setFileName(fileName);
uploadedFile.setFilePath(filePath);
uploadedFile.setOriginName(originName);
uploadedFile.setFileSize(fileSize);
uploadedFile.setFileCode(0);
// DB μ λ°μ΄ν° λ±λ‘
result = fileMapper.insert(uploadedFile);
return result;
}
}
Java
볡μ¬
β’
BoardServiceImpl.java
package com.joeun.server.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Board;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.BoardMapper;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class BoardServiceImpl implements BoardService {
@Autowired
private BoardMapper boardMapper;
@Autowired
private FileService fileService;
@Override
public List<Board> list() throws Exception {
List<Board> boardList = boardMapper.list();
return boardList;
}
@Override
public Board select(int no) throws Exception {
Board board = boardMapper.select(no);
return board;
}
@Override
@Transactional
public int insert(Board board) throws Exception {
int result = boardMapper.insert(board); // μλ‘ μμ±λ λ°μ΄ν°μ pk κ°μ Έμ΄
int parentNo = boardMapper.maxPk();
board.setNo(parentNo);
// β
(New) νμΌ μ
λ‘λ
result += uploadFiles(board);
return result;
}
@Override
public int update(Board board) throws Exception {
int result = boardMapper.update(board);
// νμΌ μ
λ‘λ
result += uploadFiles(board);
return result;
}
@Override
public int delete(int no) throws Exception {
int result = boardMapper.delete(no);
return result;
}
@Override
public int updateViews(int count, int no) throws Exception {
int result = boardMapper.updateViews(count, no);
return result;
}
// β
(New) νμΌ μ
λ‘λ
public int uploadFiles(Board board) throws Exception {
String parentTable = "board";
int parentNo = board.getNo();
int result = 0;
List<MultipartFile> fileList = board.getFiles();
if( fileList != null && !fileList.isEmpty() ) {
Files fileInfo = new Files();
fileInfo.setParentTable(parentTable);
fileInfo.setParentNo(parentNo);
result = fileService.uploadFiles(fileInfo, fileList);
}
return result;
}
}
Java
볡μ¬
Controller
β’
FileController.java
package com.joeun.server.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
@RequestMapping("/file")
public class FileController {
}
Java
볡μ¬
νμΌ μμ€ν μ λ±λ‘
1.
DTO
2.
Service
DTO
β’
Files.java
package com.joeun.server.dto;
import java.util.Date;
import org.springframework.web.multipart.MultipartFile;
import lombok.Data;
@Data
public class Files {
private int no;
private String parentTable;
private int parentNo;
private String fileName;
private String originName;
private String filePath;
private long fileSize;
private Date regDate;
private Date updDate;
private int fileCode;
MultipartFile file; // β
μΆκ°
}
Java
볡μ¬
Service
β’
FileServiceImpl.java
μΆκ°ν μ½λ
// β
(New) νμΌμ
λ‘λ
// - μλ² μΈ‘, νμΌ μμ€ν
μ νμΌ λ³΅μ¬
File uploadFile = new File(uploadPath, fileName);
FileCopyUtils.copy(fileData, uploadFile); // νμΌ μ
λ‘λ
Java
볡μ¬
package com.joeun.server.service;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.FileMapper;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class FileServiceImpl implements FileService {
@Autowired
private FileMapper fileMapper;
@Value("${upload.path}") // application.properties μ μ€μ ν μ
λ‘λ κ²½λ‘ μμ±λͺ
private String uploadPath; // μ
λ‘λ κ²½λ‘
@Override
public List<Files> list() throws Exception {
List<Files> fileList = fileMapper.list();
return fileList;
}
@Override
public Files select(int no) throws Exception {
Files file = fileMapper.select(no);
return file;
}
@Override
public int insert(Files file) throws Exception {
int result = fileMapper.insert(file);
return result;
}
@Override
public int update(Files file) throws Exception {
int result = fileMapper.update(file);
return result;
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
@Override
public int uploadFiles(Files fileInfo, List<MultipartFile> fileList) throws Exception {
int result = 0;
for (MultipartFile file : fileList) {
result += uploadFile( fileInfo, file);
}
log.info(result + "κ° νμΌμ μ
λ‘λνμμ΅λλ€.");
return result;
}
@Override
public int deleteByNoList(List<Integer> deleteFileNoList) throws Exception {
int result = 0;
if( deleteFileNoList != null && !deleteFileNoList.isEmpty() )
for (Integer deleteFileNo : deleteFileNoList) {
if( deleteFileNo == null ) continue;
fileMapper.delete(deleteFileNo);
log.info(deleteFileNo + "λ² νμΌ μμ ");
result++;
}
return result;
}
@Override
@Transactional
public int upload(Files file) throws Exception {
int result = uploadFile(file, file.getFile());
if( result > 0 )
result = fileMapper.maxPk();
return result;
}
public int uploadFile(Files fileInfo, MultipartFile file) throws Exception {
int result = 0;
if( file.isEmpty() ) return result;
// νμΌ μ 보 : μλ³ΈνμΌλͺ
, νμΌ μ©λ, νμΌ λ°μ΄ν°
String originName = file.getOriginalFilename();
long fileSize = file.getSize();
byte[] fileData = file.getBytes();
// μ
λ‘λ κ²½λ‘
// νμΌλͺ
μ€λ³΅ λ°©μ§ λ°©λ²(μ μ±
)
// - λ μ§_νμΌλͺ
.νμ₯μ
// - UID_νμΌλͺ
.νμ₯μ
// UID_κ°μμ§.png
String fileName = UUID.randomUUID().toString() + "_" + originName;
// c:/upload/UID_κ°μμ§.png
String filePath = uploadPath + "/" + fileName;
// β
(New) νμΌμ
λ‘λ
// - μλ² μΈ‘, νμΌ μμ€ν
μ νμΌ λ³΅μ¬
File uploadFile = new File(uploadPath, fileName);
FileCopyUtils.copy(fileData, uploadFile); // νμΌ μ
λ‘λ
// - DB μ νμΌ μ 보 λ±λ‘
Files uploadedFile = new Files();
uploadedFile.setParentTable(fileInfo.getParentTable());
uploadedFile.setParentNo(fileInfo.getParentNo());
uploadedFile.setFileName(fileName);
uploadedFile.setFilePath(filePath);
uploadedFile.setOriginName(originName);
uploadedFile.setFileSize(fileSize);
uploadedFile.setFileCode(0);
result = fileMapper.insert(uploadedFile);
return result;
}
}
Java
볡μ¬
οΈ νμΌ μ‘°ν
νμΌ λͺ©λ‘ μ‘°ν
β’
FileService.java
β’
FileServiceImpl.java
β’
BoardServiceImpl.java
β’
BoardController.java
FileService.java
package com.joeun.server.service;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import jakarta.servlet.http.HttpServletResponse;
public interface FileService {
// νμΌ λͺ©λ‘
public List<Files> list() throws Exception;
// νμΌ μ‘°ν
public Files select(int no) throws Exception;
// νμΌ λ±λ‘
public int insert(Files file) throws Exception;
// νμΌ μμ
public int update(Files file) throws Exception;
// νμΌ μ
λ‘λ
public int uploadFiles(Files file, List<MultipartFile> fileList) throws Exception;
// νμΌ μ
λ‘λ
public int upload(Files file) throws Exception;
// β
(New) νμΌ λͺ©λ‘ - λΆλͺ¨ κΈ°μ€
public List<Files> listByParent(Files file) throws Exception;
}
Java
볡μ¬
FileServiceImpl.java
package com.joeun.server.service;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.FileMapper;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class FileServiceImpl implements FileService {
@Autowired
private FileMapper fileMapper;
@Value("${upload.path}") // application.properties μ μ€μ ν μ
λ‘λ κ²½λ‘ μμ±λͺ
private String uploadPath; // μ
λ‘λ κ²½λ‘
@Override
public List<Files> list() throws Exception {
List<Files> fileList = fileMapper.list();
return fileList;
}
@Override
public Files select(int no) throws Exception {
Files file = fileMapper.select(no);
return file;
}
@Override
public int insert(Files file) throws Exception {
int result = fileMapper.insert(file);
return result;
}
@Override
public int update(Files file) throws Exception {
int result = fileMapper.update(file);
return result;
}
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
@Override
public int uploadFiles(Files fileInfo, List<MultipartFile> fileList) throws Exception {
int result = 0;
for (MultipartFile file : fileList) {
result += uploadFile( fileInfo, file);
}
log.info(result + "κ° νμΌμ μ
λ‘λνμμ΅λλ€.");
return result;
}
@Override
public int deleteByNoList(List<Integer> deleteFileNoList) throws Exception {
int result = 0;
if( deleteFileNoList != null && !deleteFileNoList.isEmpty() )
for (Integer deleteFileNo : deleteFileNoList) {
if( deleteFileNo == null ) continue;
fileMapper.delete(deleteFileNo);
log.info(deleteFileNo + "λ² νμΌ μμ ");
result++;
}
return result;
}
@Override
@Transactional
public int upload(Files file) throws Exception {
int result = uploadFile(file, file.getFile());
if( result > 0 )
result = fileMapper.maxPk();
return result;
}
public int uploadFile(Files fileInfo, MultipartFile file) throws Exception {
int result = 0;
if( file.isEmpty() ) return result;
// νμΌ μ 보 : μλ³ΈνμΌλͺ
, νμΌ μ©λ, νμΌ λ°μ΄ν°
String originName = file.getOriginalFilename();
long fileSize = file.getSize();
byte[] fileData = file.getBytes();
// μ
λ‘λ κ²½λ‘
// νμΌλͺ
μ€λ³΅ λ°©μ§ λ°©λ²(μ μ±
)
// - λ μ§_νμΌλͺ
.νμ₯μ
// - UID_νμΌλͺ
.νμ₯μ
// UID_κ°μμ§.png
String fileName = UUID.randomUUID().toString() + "_" + originName;
// c:/upload/UID_κ°μμ§.png
String filePath = uploadPath + "/" + fileName;
// - μλ² μΈ‘, νμΌ μμ€ν
μ νμΌ λ³΅μ¬
File uploadFile = new File(uploadPath, fileName);
FileCopyUtils.copy(fileData, uploadFile); // νμΌ μ
λ‘λ
// - DB μ νμΌ μ 보 λ±λ‘
Files uploadedFile = new Files();
uploadedFile.setParentTable(fileInfo.getParentTable());
uploadedFile.setParentNo(fileInfo.getParentNo());
uploadedFile.setFileName(fileName);
uploadedFile.setFilePath(filePath);
uploadedFile.setOriginName(originName);
uploadedFile.setFileSize(fileSize);
uploadedFile.setFileCode(0);
result = fileMapper.insert(uploadedFile);
return result;
}
// β
(New) - νμΌ λͺ©λ‘ μ‘°ν
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
}
Java
볡μ¬
BoardController.java
μΆκ°ν μ½λ
@GetMapping("/{no}")
public ResponseEntity<?> getOne(@PathVariable Integer no, Files files) {
log.info("[GET] - /boards/" + no + " - κ²μκΈ μ‘°ν");
try {
Board board = boardService.select(no);
files.setParentTable("board");
files.setParentNo(no);
List<Files> fileList = fileService.listByParent(files); // νμΌ μ 보
Map<String, Object> response = new HashMap<>();
response.put("board", board);
response.put("fileList", fileList);
if( board == null ) {
board = new Board();
board.setTitle("λ°μ΄ν° μμ");
}
return new ResponseEntity<>(response, HttpStatus.OK);
} catch (Exception e) {
log.error(null, e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Java
볡μ¬
package com.joeun.server.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Board;
import com.joeun.server.dto.Files;
import com.joeun.server.service.BoardService;
import com.joeun.server.service.FileService;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestController
@RequestMapping("/boards")
public class BoardController {
@Autowired
private BoardService boardService;
@Autowired
private FileService fileService;
// π©βπ» CRUD λ©μλ μλ μμ± : sp-crud
// π©βπ» μλ import : alt + shift + O
// π©βπ» ν μ€ μμ : ctrl + shift + K
@GetMapping()
public ResponseEntity<?> getAll() {
log.info("[GET] - /boards - κ²μκΈ λͺ©λ‘");
try {
List<Board> boardList = boardService.list();
if( boardList == null )
log.info("μ‘°νλ κ²μκΈ μμ");
else
log.info("κ²μκΈ μ : " + boardList.size());
return new ResponseEntity<>(boardList, HttpStatus.OK);
} catch (Exception e) {
log.error(null, e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@GetMapping("/{no}")
public ResponseEntity<?> getOne(@PathVariable Integer no, Files files) {
log.info("[GET] - /boards/" + no + " - κ²μκΈ μ‘°ν");
try {
Board board = boardService.select(no);
files.setParentTable("board");
files.setParentNo(no);
List<Files> fileList = fileService.listByParent(files); // νμΌ μ 보
Map<String, Object> response = new HashMap<>();
response.put("board", board);
response.put("fileList", fileList);
if( board == null ) {
board = new Board();
board.setTitle("λ°μ΄ν° μμ");
}
return new ResponseEntity<>(response, HttpStatus.OK);
} catch (Exception e) {
log.error(null, e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PostMapping()
// public ResponseEntity<?> create(@RequestBody Board board) { // Content-Type : application/json
public ResponseEntity<?> create(Board board) { // Content-Type : multipart/form-data
log.info("[POST] - /boards - κ²μκΈ λ±λ‘");
log.info("board : " + board.toString());
List<MultipartFile> files = board.getFiles();
if( files != null )
for (MultipartFile file : files) {
log.info("file : " + file.getOriginalFilename());
}
try {
int result = boardService.insert(board);
if( result > 0 )
return new ResponseEntity<>("κ²μκΈ λ±λ‘ μλ£", HttpStatus.CREATED); // 201
else
return new ResponseEntity<>("κ²μκΈ λ±λ‘ μ€ν¨", HttpStatus.OK);
} catch (Exception e) {
log.error(null, e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PutMapping()
// public ResponseEntity<?> update(@RequestBody Board board) { // Content-Type : application/json
public ResponseEntity<?> update(Board board) { // Content-Type : multipart/form-data
log.info("[PUT] - /boards - κ²μκΈ μμ ");
try {
int result = boardService.update(board);
log.info("μμ : " + board);
if( result > 0 )
return new ResponseEntity<>("κ²μκΈ μμ μλ£", HttpStatus.OK);
else
return new ResponseEntity<>("κ²μκΈ μμ μ€ν¨", HttpStatus.OK);
} catch (Exception e) {
log.error(null, e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@DeleteMapping("/{no}")
public ResponseEntity<?> destroy(@PathVariable Integer no) {
log.info("[DELETE] - /boards/" + no + " - κ²μκΈ μμ ");
try {
int result = boardService.delete(no);
if( result > 0 )
return new ResponseEntity<>("κ²μκΈ μμ μλ£", HttpStatus.OK);
else
return new ResponseEntity<>("κ²μκΈ μμ μ€ν¨", HttpStatus.OK);
} catch (Exception e) {
log.error(null, e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
Java
볡μ¬
λ€μ΄λ‘λ
β’
FileService.java
β’
FileServiceImpl.java
β’
FileController.java
FileService.java
package com.joeun.server.service;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import jakarta.servlet.http.HttpServletResponse;
public interface FileService {
// νμΌ λͺ©λ‘
public List<Files> list() throws Exception;
// νμΌ μ‘°ν
public Files select(int no) throws Exception;
// νμΌ λ±λ‘
public int insert(Files file) throws Exception;
// νμΌ μμ
public int update(Files file) throws Exception;
// νμΌ μ
λ‘λ
public int uploadFiles(Files file, List<MultipartFile> fileList) throws Exception;
// νμΌ μ
λ‘λ
public int upload(Files file) throws Exception;
// νμΌ λͺ©λ‘ - λΆλͺ¨ κΈ°μ€
public List<Files> listByParent(Files file) throws Exception;
// β
(New) - νμΌ λ€μ΄λ‘λ
public int download(int no, HttpServletResponse response) throws Exception;
}
Java
볡μ¬
FileServiceImpl.java
package com.joeun.server.service;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.FileMapper;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class FileServiceImpl implements FileService {
@Autowired
private FileMapper fileMapper;
@Value("${upload.path}") // application.properties μ μ€μ ν μ
λ‘λ κ²½λ‘ μμ±λͺ
private String uploadPath; // μ
λ‘λ κ²½λ‘
@Override
public List<Files> list() throws Exception {
List<Files> fileList = fileMapper.list();
return fileList;
}
@Override
public Files select(int no) throws Exception {
Files file = fileMapper.select(no);
return file;
}
@Override
public int insert(Files file) throws Exception {
int result = fileMapper.insert(file);
return result;
}
@Override
public int update(Files file) throws Exception {
int result = fileMapper.update(file);
return result;
}
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
@Override
public int uploadFiles(Files fileInfo, List<MultipartFile> fileList) throws Exception {
int result = 0;
for (MultipartFile file : fileList) {
result += uploadFile( fileInfo, file);
}
log.info(result + "κ° νμΌμ μ
λ‘λνμμ΅λλ€.");
return result;
}
@Override
public int deleteByNoList(List<Integer> deleteFileNoList) throws Exception {
int result = 0;
if( deleteFileNoList != null && !deleteFileNoList.isEmpty() )
for (Integer deleteFileNo : deleteFileNoList) {
if( deleteFileNo == null ) continue;
fileMapper.delete(deleteFileNo);
log.info(deleteFileNo + "λ² νμΌ μμ ");
result++;
}
return result;
}
@Override
@Transactional
public int upload(Files file) throws Exception {
int result = uploadFile(file, file.getFile());
if( result > 0 )
result = fileMapper.maxPk();
return result;
}
public int uploadFile(Files fileInfo, MultipartFile file) throws Exception {
int result = 0;
if( file.isEmpty() ) return result;
// νμΌ μ 보 : μλ³ΈνμΌλͺ
, νμΌ μ©λ, νμΌ λ°μ΄ν°
String originName = file.getOriginalFilename();
long fileSize = file.getSize();
byte[] fileData = file.getBytes();
// μ
λ‘λ κ²½λ‘
// νμΌλͺ
μ€λ³΅ λ°©μ§ λ°©λ²(μ μ±
)
// - λ μ§_νμΌλͺ
.νμ₯μ
// - UID_νμΌλͺ
.νμ₯μ
// UID_κ°μμ§.png
String fileName = UUID.randomUUID().toString() + "_" + originName;
// c:/upload/UID_κ°μμ§.png
String filePath = uploadPath + "/" + fileName;
// - μλ² μΈ‘, νμΌ μμ€ν
μ νμΌ λ³΅μ¬
File uploadFile = new File(uploadPath, fileName);
FileCopyUtils.copy(fileData, uploadFile); // νμΌ μ
λ‘λ
// - DB μ νμΌ μ 보 λ±λ‘
Files uploadedFile = new Files();
uploadedFile.setParentTable(fileInfo.getParentTable());
uploadedFile.setParentNo(fileInfo.getParentNo());
uploadedFile.setFileName(fileName);
uploadedFile.setFilePath(filePath);
uploadedFile.setOriginName(originName);
uploadedFile.setFileSize(fileSize);
uploadedFile.setFileCode(0);
result = fileMapper.insert(uploadedFile);
return result;
}
// νμΌ λͺ©λ‘ μ‘°ν
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int download(int fileNo, HttpServletResponse response) throws Exception {
// result
// 0 : νμΌ λ€μ΄λ‘λ μ²λ¦¬ μ€ν¨
// 1 : νμΌ λ€μ΄λ‘λ μ±κ³΅
Files file = fileMapper.select(fileNo);
if( file == null ) {
// BAD_REQUEST : 400, ν΄λΌμ΄μΈνΈμ μμ²μ΄ μλͺ»λμμμ μλ €μ£Όλ μνμ½λ
// response.setStatus(response.SC_BAD_REQUEST);
return 0;
}
String filePath = file.getFilePath(); // νμΌ κ²½λ‘
String fileName = file.getFileName(); // νμΌ μ΄λ¦
// λ€μ΄λ‘λ μλ΅μ μν ν€λ μΈν
// - ContentType : application/octet-stream
// - Content-Disposition : attachment, filename="νμΌλͺ
.νμ₯μ"
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
// νμΌ λ€μ΄λ‘λ
// - νμΌ μ
λ ₯
File downloadFile = new File(filePath);
FileInputStream fis = new FileInputStream(downloadFile);
// - νμΌ μΆλ ₯
ServletOutputStream sos = response.getOutputStream();
// λ€μ΄λ‘λ
FileCopyUtils.copy(fis, sos);
fis.close();
sos.close();
return 1;
}
}
Java
볡μ¬
FileController.java
package com.joeun.server.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
@RequestMapping("/file")
public class FileController {
@Autowired
private FileService fileService;
/**
* νμΌ λ€μ΄λ‘λ
* @param fileNo
* @param response
* @throws Exception
*/
@GetMapping("/{no}")
public void fileDownload(@PathVariable("no") int no
,HttpServletResponse response) throws Exception {
// νμΌ μ‘°ν
Files file = fileService.select(no);
// νμΌμ΄ μ‘΄μ¬νμ§ μμΌλ©΄,
if( file == null ) {
// μλ΅ μνμ½λ : 400, ν΄λΌμ΄μΈνΈμ μμ²μ΄ μλͺ»λμμμ λνλ΄λ μνμ½λ
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}
String fileName = file.getFileName(); // νμΌ λͺ
String filePath = file.getFilePath(); // νμΌ κ²½λ‘
// νμΌ λ€μ΄λ‘λλ₯Ό μν ν€λ μΈν
// - ContentType : application/octet-straem
// - Content-Disposition : attachment; fileanme="νμΌλͺ
.νμ₯μ"
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
// νμΌ μ
λ ₯
File downloadFile = new File(filePath);
FileInputStream fis = new FileInputStream(downloadFile);
ServletOutputStream sos = response.getOutputStream();
// λ€μ΄λ‘λ
FileCopyUtils.copy(fis, sos);
}
}
Java
볡μ¬
μΈλ€μΌ μ΄λ―Έμ§ 보기
β’
FileController.java
FileController.java
package com.joeun.server.controller;
import java.io.File;
import java.io.FileInputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.joeun.server.dto.Files;
import com.joeun.server.service.FileService;
import com.joeun.server.utils.MediaUtil;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
@RequestMapping("/file")
public class FileController {
@Autowired
private FileService fileService;
@Autowired
private ResourceLoader resourceLoader;
/**
* νμΌ λ€μ΄λ‘λ
* @param fileNo
* @param response
* @throws Exception
*/
@GetMapping("/{no}")
public void fileDownload(@PathVariable("no") int no
,HttpServletResponse response) throws Exception {
// νμΌ μ‘°ν
Files file = fileService.select(no);
// νμΌμ΄ μ‘΄μ¬νμ§ μμΌλ©΄,
if( file == null ) {
// μλ΅ μνμ½λ : 400, ν΄λΌμ΄μΈνΈμ μμ²μ΄ μλͺ»λμμμ λνλ΄λ μνμ½λ
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}
String fileName = file.getFileName(); // νμΌ λͺ
String filePath = file.getFilePath(); // νμΌ κ²½λ‘
// νμΌ λ€μ΄λ‘λλ₯Ό μν ν€λ μΈν
// - ContentType : application/octet-straem
// - Content-Disposition : attachment; fileanme="νμΌλͺ
.νμ₯μ"
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
// νμΌ μ
λ ₯
File downloadFile = new File(filePath);
FileInputStream fis = new FileInputStream(downloadFile);
ServletOutputStream sos = response.getOutputStream();
// λ€μ΄λ‘λ
FileCopyUtils.copy(fis, sos);
}
/**
* μ΄λ―Έμ§ μΈλ€μΌ
* @param no
* @param response
* @throws Exception
*/
@GetMapping("/img/{no}")
public void showImg(@PathVariable Integer no, HttpServletResponse response) throws Exception {
Files file = fileService.select(no);
String filePath = (file != null) ? file.getFilePath() : null;
Resource resource = resourceLoader.getResource("classpath:static/img/no-image.png");
File imgFile;
if (filePath == null || !(imgFile = new File(filePath)).exists()) {
// νμΌμ΄ μ‘΄μ¬νμ§ μκ±°λ νμΌ κ²½λ‘κ° nullμΈ κ²½μ°
imgFile = resource.getFile();
}
String ext = filePath.substring(filePath.lastIndexOf(".") + 1);
MediaType mType = MediaUtil.getMediaType(ext);
if (mType == null) {
// μ΄λ―Έμ§ νμ
μ΄ μλ κ²½μ°
response.setContentType(MediaType.IMAGE_PNG_VALUE); // κΈ°λ³Έμ μΌλ‘ PNGλ‘ μ€μ
imgFile = resource.getFile();
} else {
// μ΄λ―Έμ§ νμ
μΌ κ²½μ°
response.setContentType(mType.toString());
}
FileInputStream fis = new FileInputStream(imgFile);
ServletOutputStream sos = response.getOutputStream();
FileCopyUtils.copy(fis, sos);
}
}
Java
볡μ¬
νμΌ μμ
κ²μκΈμ μ’ μλ μ¬λ¬ νμΌ μμ
β’
FileService.java
β’
FileServiceImpl.java
β’
BoardServiceImpl.java
β’
FileService.java
package com.joeun.server.service;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import jakarta.servlet.http.HttpServletResponse;
public interface FileService {
// νμΌ λͺ©λ‘
public List<Files> list() throws Exception;
// νμΌ μ‘°ν
public Files select(int no) throws Exception;
// νμΌ λ±λ‘
public int insert(Files file) throwsdeleteByParent Exception;
// νμΌ μμ
public int update(Files file) throws Exception;
// νμΌ μμ
public int delete(int no) throws Exception;
// νμΌ μ
λ‘λ
public int uploadFiles(Files file, List<MultipartFile> fileList) throws Exception;
// νμΌ μ
λ‘λ
public int upload(Files file) throws Exception;
// νμΌ λͺ©λ‘ - λΆλͺ¨ κΈ°μ€
public List<Files> listByParent(Files file) throws Exception;
// νμΌ λ€μ΄λ‘λ
public int download(int no, HttpServletResponse response) throws Exception;
// β
(New) νμΌ μμ - λΆλͺ¨ κΈ°μ€
public int deleteByParent(Files fileInfo) throws Exception;
}
Java
볡μ¬
β’
FileServiceImpl.java
μΆκ°ν μ½λ
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
Java
볡μ¬
package com.joeun.server.service;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.FileMapper;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class FileServiceImpl implements FileService {
@Autowired
private FileMapper fileMapper;
@Value("${upload.path}") // application.properties μ μ€μ ν μ
λ‘λ κ²½λ‘ μμ±λͺ
private String uploadPath; // μ
λ‘λ κ²½λ‘
@Override
public List<Files> list() throws Exception {
List<Files> fileList = fileMapper.list();
return fileList;
}
@Override
public Files select(int no) throws Exception {
Files file = fileMapper.select(no);
return file;
}
@Override
public int insert(Files file) throws Exception {
int result = fileMapper.insert(file);
return result;
}
@Override
public int update(Files file) throws Exception {
int result = fileMapper.update(file);
return result;
}
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
@Override
public int uploadFiles(Files fileInfo, List<MultipartFile> fileList) throws Exception {
int result = 0;
for (MultipartFile file : fileList) {
result += uploadFile( fileInfo, file);
}
log.info(result + "κ° νμΌμ μ
λ‘λνμμ΅λλ€.");
return result;
}
@Override
public int deleteByNoList(List<Integer> deleteFileNoList) throws Exception {
int result = 0;
if( deleteFileNoList != null && !deleteFileNoList.isEmpty() )
for (Integer deleteFileNo : deleteFileNoList) {
if( deleteFileNo == null ) continue;
fileMapper.delete(deleteFileNo);
log.info(deleteFileNo + "λ² νμΌ μμ ");
result++;
}
return result;
}
@Override
@Transactional
public int upload(Files file) throws Exception {
int result = uploadFile(file, file.getFile());
if( result > 0 )
result = fileMapper.maxPk();
return result;
}
public int uploadFile(Files fileInfo, MultipartFile file) throws Exception {
int result = 0;
if( file.isEmpty() ) return result;
// νμΌ μ 보 : μλ³ΈνμΌλͺ
, νμΌ μ©λ, νμΌ λ°μ΄ν°
String originName = file.getOriginalFilename();
long fileSize = file.getSize();
byte[] fileData = file.getBytes();
// μ
λ‘λ κ²½λ‘
// νμΌλͺ
μ€λ³΅ λ°©μ§ λ°©λ²(μ μ±
)
// - λ μ§_νμΌλͺ
.νμ₯μ
// - UID_νμΌλͺ
.νμ₯μ
// UID_κ°μμ§.png
String fileName = UUID.randomUUID().toString() + "_" + originName;
// c:/upload/UID_κ°μμ§.png
String filePath = uploadPath + "/" + fileName;
// - μλ² μΈ‘, νμΌ μμ€ν
μ νμΌ λ³΅μ¬
File uploadFile = new File(uploadPath, fileName);
FileCopyUtils.copy(fileData, uploadFile); // νμΌ μ
λ‘λ
// - DB μ νμΌ μ 보 λ±λ‘
Files uploadedFile = new Files();
uploadedFile.setParentTable(fileInfo.getParentTable());
uploadedFile.setParentNo(fileInfo.getParentNo());
uploadedFile.setFileName(fileName);
uploadedFile.setFilePath(filePath);
uploadedFile.setOriginName(originName);
uploadedFile.setFileSize(fileSize);
uploadedFile.setFileCode(0);
result = fileMapper.insert(uploadedFile);
return result;
}
// νμΌ λͺ©λ‘ μ‘°ν
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int download(int fileNo, HttpServletResponse response) throws Exception {
// result
// 0 : νμΌ λ€μ΄λ‘λ μ²λ¦¬ μ€ν¨
// 1 : νμΌ λ€μ΄λ‘λ μ±κ³΅
Files file = fileMapper.select(fileNo);
if( file == null ) {
// BAD_REQUEST : 400, ν΄λΌμ΄μΈνΈμ μμ²μ΄ μλͺ»λμμμ μλ €μ£Όλ μνμ½λ
// response.setStatus(response.SC_BAD_REQUEST);
return 0;
}
String filePath = file.getFilePath(); // νμΌ κ²½λ‘
String fileName = file.getFileName(); // νμΌ μ΄λ¦
// λ€μ΄λ‘λ μλ΅μ μν ν€λ μΈν
// - ContentType : application/octet-stream
// - Content-Disposition : attachment, filename="νμΌλͺ
.νμ₯μ"
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
// νμΌ λ€μ΄λ‘λ
// - νμΌ μ
λ ₯
File downloadFile = new File(filePath);
FileInputStream fis = new FileInputStream(downloadFile);
// - νμΌ μΆλ ₯
ServletOutputStream sos = response.getOutputStream();
// λ€μ΄λ‘λ
FileCopyUtils.copy(fis, sos);
fis.close();
sos.close();
return 1;
}
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
}
Java
볡μ¬
β’
BoardServiceImpl.java
μΆκ°ν μ½λ
@Override
@Transactional
public int delete(int no) throws Exception {
int result = boardMapper.delete(no);
String parentTable = "board";
int parentNo = no;
if( result > 0 ) {
Files fileInfo = new Files();
fileInfo.setParentTable(parentTable);
fileInfo.setParentNo(parentNo);
int fileResult = fileService.deleteByParent(fileInfo);
result = fileResult;
}
return result;
}
Java
볡μ¬
package com.joeun.server.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Board;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.BoardMapper;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class BoardServiceImpl implements BoardService {
@Autowired
private BoardMapper boardMapper;
@Autowired
private FileService fileService;
@Override
public List<Board> list() throws Exception {
List<Board> boardList = boardMapper.list();
return boardList;
}
@Override
public Board select(int no) throws Exception {
Board board = boardMapper.select(no);
return board;
}
@Override
@Transactional
public int insert(Board board) throws Exception {
int result = boardMapper.insert(board); // μλ‘ μμ±λ λ°μ΄ν°μ pk κ°μ Έμ΄
int parentNo = boardMapper.maxPk();
board.setNo(parentNo);
result += uploadFiles(board);
return result;
}
@Override
public int update(Board board) throws Exception {
int result = boardMapper.update(board);
// νμΌ μ
λ‘λ
result += uploadFiles(board);
return result;
}
@Override
public int updateViews(int count, int no) throws Exception {
int result = boardMapper.updateViews(count, no);
return result;
}
public int uploadFiles(Board board) throws Exception {
String parentTable = "board";
int parentNo = board.getNo();
int result = 0;
List<MultipartFile> fileList = board.getFiles();
if( fileList != null && !fileList.isEmpty() ) {
Files fileInfo = new Files();
fileInfo.setParentTable(parentTable);
fileInfo.setParentNo(parentNo);
result = fileService.uploadFiles(fileInfo, fileList);
}
return result;
}
@Override
@Transactional
public int delete(int no) throws Exception {
int result = boardMapper.delete(no);
String parentTable = "board";
int parentNo = no;
// β
(New) - κ²μκΈμ μ’
μλ νμΌ μμ
if( result > 0 ) {
Files fileInfo = new Files();
fileInfo.setParentTable(parentTable);
fileInfo.setParentNo(parentNo);
int fileResult = fileService.deleteByParent(fileInfo);
result = fileResult;
}
return result;
}
}
Java
볡μ¬
μ ν νμΌ μμ
β’
FileService.java
β’
FileServiceImpl.java
β’
BoardServiceImpl.java
β’
FileService.java
package com.joeun.server.service;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import jakarta.servlet.http.HttpServletResponse;
public interface FileService {
// νμΌ λͺ©λ‘
public List<Files> list() throws Exception;
// νμΌ μ‘°ν
public Files select(int no) throws Exception;
// νμΌ λ±λ‘
public int insert(Files file) throws Exception;
// νμΌ μμ
public int update(Files file) throws Exception;
// νμΌ μμ
public int delete(int no) throws Exception;
// νμΌ μ
λ‘λ
public int uploadFiles(Files file, List<MultipartFile> fileList) throws Exception;
// νμΌ μ
λ‘λ
public int upload(Files file) throws Exception;
// νμΌ λͺ©λ‘ - λΆλͺ¨ κΈ°μ€
public List<Files> listByParent(Files file) throws Exception;
// νμΌ λ€μ΄λ‘λ
public int download(int no, HttpServletResponse response) throws Exception;
// νμΌ μμ - λΆλͺ¨ κΈ°μ€
public int deleteByParent(Files fileInfo) throws Exception;
// νμΌ μμ - noList κΈ°μ€
public int deleteByNoList(List<Integer> noList) throws Exception;
}
Java
볡μ¬
β’
FileServiceImpl.java
μΆκ°ν μ½λ
@Override
public int deleteByNoList(List<Integer> deleteFileNoList) throws Exception {
int result = 0;
if( deleteFileNoList != null && !deleteFileNoList.isEmpty() )
for (Integer deleteFileNo : deleteFileNoList) {
if( deleteFileNo == null ) continue;
fileMapper.delete(deleteFileNo);
log.info(deleteFileNo + "λ² νμΌ μμ ");
result++;
}
return result;
}
Java
볡μ¬
package com.joeun.server.service;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.FileMapper;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class FileServiceImpl implements FileService {
@Autowired
private FileMapper fileMapper;
@Value("${upload.path}") // application.properties μ μ€μ ν μ
λ‘λ κ²½λ‘ μμ±λͺ
private String uploadPath; // μ
λ‘λ κ²½λ‘
@Override
public List<Files> list() throws Exception {
List<Files> fileList = fileMapper.list();
return fileList;
}
@Override
public Files select(int no) throws Exception {
Files file = fileMapper.select(no);
return file;
}
@Override
public int insert(Files file) throws Exception {
int result = fileMapper.insert(file);
return result;
}
@Override
public int update(Files file) throws Exception {
int result = fileMapper.update(file);
return result;
}
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
@Override
public int uploadFiles(Files fileInfo, List<MultipartFile> fileList) throws Exception {
int result = 0;
for (MultipartFile file : fileList) {
result += uploadFile( fileInfo, file);
}
log.info(result + "κ° νμΌμ μ
λ‘λνμμ΅λλ€.");
return result;
}
@Override
public int deleteByNoList(List<Integer> deleteFileNoList) throws Exception {
int result = 0;
if( deleteFileNoList != null && !deleteFileNoList.isEmpty() )
for (Integer deleteFileNo : deleteFileNoList) {
if( deleteFileNo == null ) continue;
fileMapper.delete(deleteFileNo);
log.info(deleteFileNo + "λ² νμΌ μμ ");
result++;
}
return result;
}
@Override
@Transactional
public int upload(Files file) throws Exception {
int result = uploadFile(file, file.getFile());
if( result > 0 )
result = fileMapper.maxPk();
return result;
}
public int uploadFile(Files fileInfo, MultipartFile file) throws Exception {
int result = 0;
if( file.isEmpty() ) return result;
// νμΌ μ 보 : μλ³ΈνμΌλͺ
, νμΌ μ©λ, νμΌ λ°μ΄ν°
String originName = file.getOriginalFilename();
long fileSize = file.getSize();
byte[] fileData = file.getBytes();
// μ
λ‘λ κ²½λ‘
// νμΌλͺ
μ€λ³΅ λ°©μ§ λ°©λ²(μ μ±
)
// - λ μ§_νμΌλͺ
.νμ₯μ
// - UID_νμΌλͺ
.νμ₯μ
// UID_κ°μμ§.png
String fileName = UUID.randomUUID().toString() + "_" + originName;
// c:/upload/UID_κ°μμ§.png
String filePath = uploadPath + "/" + fileName;
// - μλ² μΈ‘, νμΌ μμ€ν
μ νμΌ λ³΅μ¬
File uploadFile = new File(uploadPath, fileName);
FileCopyUtils.copy(fileData, uploadFile); // νμΌ μ
λ‘λ
// - DB μ νμΌ μ 보 λ±λ‘
Files uploadedFile = new Files();
uploadedFile.setParentTable(fileInfo.getParentTable());
uploadedFile.setParentNo(fileInfo.getParentNo());
uploadedFile.setFileName(fileName);
uploadedFile.setFilePath(filePath);
uploadedFile.setOriginName(originName);
uploadedFile.setFileSize(fileSize);
uploadedFile.setFileCode(0);
result = fileMapper.insert(uploadedFile);
return result;
}
// νμΌ λͺ©λ‘ μ‘°ν
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int download(int fileNo, HttpServletResponse response) throws Exception {
// result
// 0 : νμΌ λ€μ΄λ‘λ μ²λ¦¬ μ€ν¨
// 1 : νμΌ λ€μ΄λ‘λ μ±κ³΅
Files file = fileMapper.select(fileNo);
if( file == null ) {
// BAD_REQUEST : 400, ν΄λΌμ΄μΈνΈμ μμ²μ΄ μλͺ»λμμμ μλ €μ£Όλ μνμ½λ
// response.setStatus(response.SC_BAD_REQUEST);
return 0;
}
String filePath = file.getFilePath(); // νμΌ κ²½λ‘
String fileName = file.getFileName(); // νμΌ μ΄λ¦
// λ€μ΄λ‘λ μλ΅μ μν ν€λ μΈν
// - ContentType : application/octet-stream
// - Content-Disposition : attachment, filename="νμΌλͺ
.νμ₯μ"
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
// νμΌ λ€μ΄λ‘λ
// - νμΌ μ
λ ₯
File downloadFile = new File(filePath);
FileInputStream fis = new FileInputStream(downloadFile);
// - νμΌ μΆλ ₯
ServletOutputStream sos = response.getOutputStream();
// λ€μ΄λ‘λ
FileCopyUtils.copy(fis, sos);
fis.close();
sos.close();
return 1;
}
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
@Override
public int deleteByNoList(List<Integer> deleteFileNoList) throws Exception {
int result = 0;
if( deleteFileNoList != null && !deleteFileNoList.isEmpty() )
for (Integer deleteFileNo : deleteFileNoList) {
if( deleteFileNo == null ) continue;
fileMapper.delete(deleteFileNo);
log.info(deleteFileNo + "λ² νμΌ μμ ");
result++;
}
return result;
}
}
Java
볡μ¬
β’
BoardServiceImpl.java
μΆκ°ν μ½λ
@Override
public int update(Board board) throws Exception {
int result = boardMapper.update(board);
// νμΌ μ
λ‘λ
result += uploadFiles(board);
// κ°λ³ νμΌ μμ
List<Integer> deleteFileNoList = board.getDeleteFileNoList();
result += fileService.deleteByNoList(deleteFileNoList);
return result;
}
Java
볡μ¬
package com.joeun.server.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Board;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.BoardMapper;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class BoardServiceImpl implements BoardService {
@Autowired
private BoardMapper boardMapper;
@Autowired
private FileService fileService;
@Override
public List<Board> list() throws Exception {
List<Board> boardList = boardMapper.list();
return boardList;
}
@Override
public Board select(int no) throws Exception {
Board board = boardMapper.select(no);
return board;
}
@Override
@Transactional
public int insert(Board board) throws Exception {
int result = boardMapper.insert(board); // μλ‘ μμ±λ λ°μ΄ν°μ pk κ°μ Έμ΄
int parentNo = boardMapper.maxPk();
board.setNo(parentNo);
result += uploadFiles(board);
return result;
}
@Override
public int update(Board board) throws Exception {
int result = boardMapper.update(board);
// νμΌ μ
λ‘λ
result += uploadFiles(board);
// β
(New) κ°λ³ νμΌ μμ
List<Integer> deleteFileNoList = board.getDeleteFileNoList();
result += fileService.deleteByNoList(deleteFileNoList);
return result;
}
@Override
public int updateViews(int count, int no) throws Exception {
int result = boardMapper.updateViews(count, no);
return result;
}
public int uploadFiles(Board board) throws Exception {
String parentTable = "board";
int parentNo = board.getNo();
int result = 0;
List<MultipartFile> fileList = board.getFiles();
if( fileList != null && !fileList.isEmpty() ) {
Files fileInfo = new Files();
fileInfo.setParentTable(parentTable);
fileInfo.setParentNo(parentNo);
result = fileService.uploadFiles(fileInfo, fileList);
}
return result;
}
@Override
@Transactional
public int delete(int no) throws Exception {
int result = boardMapper.delete(no);
String parentTable = "board";
int parentNo = no;
if( result > 0 ) {
Files fileInfo = new Files();
fileInfo.setParentTable(parentTable);
fileInfo.setParentNo(parentNo);
int fileResult = fileService.deleteByParent(fileInfo);
result = fileResult;
}
return result;
}
}
Java
볡μ¬
κ°λ³ νμΌ μμ
β’
FileService.java
β’
FileServiceImpl.java
β’
FileController.java
FileService.java
// νμΌ μμ
public int delete(int no) throws Exception;
Java
볡μ¬
package com.joeun.server.service;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import jakarta.servlet.http.HttpServletResponse;
public interface FileService {
// νμΌ λͺ©λ‘
public List<Files> list() throws Exception;
// νμΌ μ‘°ν
public Files select(int no) throws Exception;
// νμΌ λ±λ‘
public int insert(Files file) throws Exception;
// νμΌ μμ
public int update(Files file) throws Exception;
// νμΌ μμ
public int delete(int no) throws Exception;
// νμΌ μ
λ‘λ
public int uploadFiles(Files file, List<MultipartFile> fileList) throws Exception;
// νμΌ μ
λ‘λ
public int upload(Files file) throws Exception;
// νμΌ λͺ©λ‘ - λΆλͺ¨ κΈ°μ€
public List<Files> listByParent(Files file) throws Exception;
// νμΌ λ€μ΄λ‘λ
public int download(int no, HttpServletResponse response) throws Exception;
// νμΌ μμ - λΆλͺ¨ κΈ°μ€
public int deleteByParent(Files fileInfo) throws Exception;
// νμΌ μμ - noList κΈ°μ€
public int deleteByNoList(List<Integer> noList) throws Exception;
}
Java
볡μ¬
FileServiceImpl.java
@Override
public int delete(int no) throws Exception {
Files file = fileMapper.select(no);
if( file == null ) return 0;
String filePath = file.getFilePath();
File deleteFile = new File(filePath);
if( !deleteFile.exists() ) return 0;
boolean deleted = deleteFile.delete();
int result = 0;
if( deleted ) {
result = fileMapper.delete(no);
}
return result;
}
Java
볡μ¬
package com.joeun.server.service;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.FileMapper;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class FileServiceImpl implements FileService {
@Autowired
private FileMapper fileMapper;
@Value("${upload.path}") // application.properties μ μ€μ ν μ
λ‘λ κ²½λ‘ μμ±λͺ
private String uploadPath; // μ
λ‘λ κ²½λ‘
@Override
public List<Files> list() throws Exception {
List<Files> fileList = fileMapper.list();
return fileList;
}
@Override
public Files select(int no) throws Exception {
Files file = fileMapper.select(no);
return file;
}
@Override
public int insert(Files file) throws Exception {
int result = fileMapper.insert(file);
return result;
}
@Override
public int update(Files file) throws Exception {
int result = fileMapper.update(file);
return result;
}
@Override
public int delete(int no) throws Exception {
Files file = fileMapper.select(no);
if( file == null ) return 0;
String filePath = file.getFilePath();
File deleteFile = new File(filePath);
if( !deleteFile.exists() ) return 0;
boolean deleted = deleteFile.delete();
int result = 0;
if( deleted ) {
result = fileMapper.delete(no);
}
return result;
}
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
@Override
public int download(int fileNo, HttpServletResponse response) throws Exception {
// result
// 0 : νμΌ λ€μ΄λ‘λ μ²λ¦¬ μ€ν¨
// 1 : νμΌ λ€μ΄λ‘λ μ±κ³΅
Files file = fileMapper.select(fileNo);
if( file == null ) {
// BAD_REQUEST : 400, ν΄λΌμ΄μΈνΈμ μμ²μ΄ μλͺ»λμμμ μλ €μ£Όλ μνμ½λ
// response.setStatus(response.SC_BAD_REQUEST);
return 0;
}
String filePath = file.getFilePath(); // νμΌ κ²½λ‘
String fileName = file.getFileName(); // νμΌ μ΄λ¦
// λ€μ΄λ‘λ μλ΅μ μν ν€λ μΈν
// - ContentType : application/octet-stream
// - Content-Disposition : attachment, filename="νμΌλͺ
.νμ₯μ"
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
// νμΌ λ€μ΄λ‘λ
// - νμΌ μ
λ ₯
File downloadFile = new File(filePath);
FileInputStream fis = new FileInputStream(downloadFile);
// - νμΌ μΆλ ₯
ServletOutputStream sos = response.getOutputStream();
// λ€μ΄λ‘λ
FileCopyUtils.copy(fis, sos);
// byte[] buffer = new byte[1024]; // 1024bytes = 1KB λ¨μ λ²νΌ
// int data;
// while( (data = fis.read(buffer)) != -1 ) { // 1KB μ© νμΌμ
λ ₯
// sos.write(buffer, 0, data); // 1KB μ© νμΌμΆλ ₯
// }
fis.close();
sos.close();
return 1;
}
@Override
public int uploadFiles(Files fileInfo, List<MultipartFile> fileList) throws Exception {
int result = 0;
for (MultipartFile file : fileList) {
result += uploadFile( fileInfo, file);
}
log.info(result + "κ° νμΌμ μ
λ‘λνμμ΅λλ€.");
return result;
}
@Override
public int deleteByNoList(List<Integer> deleteFileNoList) throws Exception {
int result = 0;
if( deleteFileNoList != null && !deleteFileNoList.isEmpty() )
for (Integer deleteFileNo : deleteFileNoList) {
if( deleteFileNo == null ) continue;
fileMapper.delete(deleteFileNo);
log.info(deleteFileNo + "λ² νμΌ μμ ");
result++;
}
return result;
}
@Override
@Transactional
public int upload(Files file) throws Exception {
int result = uploadFile(file, file.getFile());
if( result > 0 )
result = fileMapper.maxPk();
return result;
}
public int uploadFile(Files fileInfo, MultipartFile file) throws Exception {
int result = 0;
if( file.isEmpty() ) return result;
// νμΌ μ 보 : μλ³ΈνμΌλͺ
, νμΌ μ©λ, νμΌ λ°μ΄ν°
String originName = file.getOriginalFilename();
long fileSize = file.getSize();
byte[] fileData = file.getBytes();
// μ
λ‘λ κ²½λ‘
// νμΌλͺ
μ€λ³΅ λ°©μ§ λ°©λ²(μ μ±
)
// - λ μ§_νμΌλͺ
.νμ₯μ
// - UID_νμΌλͺ
.νμ₯μ
// UID_κ°μμ§.png
String fileName = UUID.randomUUID().toString() + "_" + originName;
// c:/upload/UID_κ°μμ§.png
String filePath = uploadPath + "/" + fileName;
// - μλ² μΈ‘, νμΌ μμ€ν
μ νμΌ λ³΅μ¬
File uploadFile = new File(uploadPath, fileName);
FileCopyUtils.copy(fileData, uploadFile); // νμΌ μ
λ‘λ
// - DB μ νμΌ μ 보 λ±λ‘
Files uploadedFile = new Files();
uploadedFile.setParentTable(fileInfo.getParentTable());
uploadedFile.setParentNo(fileInfo.getParentNo());
uploadedFile.setFileName(fileName);
uploadedFile.setFilePath(filePath);
uploadedFile.setOriginName(originName);
uploadedFile.setFileSize(fileSize);
uploadedFile.setFileCode(0);
result = fileMapper.insert(uploadedFile);
return result;
}
}
Java
볡μ¬
FileController.java
package com.joeun.server.controller;
import java.io.File;
import java.io.FileInputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.joeun.server.dto.Files;
import com.joeun.server.service.FileService;
import com.joeun.server.utils.MediaUtil;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
@RequestMapping("/file")
public class FileController {
@Autowired
private FileService fileService;
@Autowired
private ResourceLoader resourceLoader;
/**
* νμΌ λ€μ΄λ‘λ
* @param fileNo
* @param response
* @throws Exception
*/
@GetMapping("/{no}")
public void fileDownload(@PathVariable("no") int no
,HttpServletResponse response) throws Exception {
// νμΌ μ‘°ν
Files file = fileService.select(no);
// νμΌμ΄ μ‘΄μ¬νμ§ μμΌλ©΄,
if( file == null ) {
// μλ΅ μνμ½λ : 400, ν΄λΌμ΄μΈνΈμ μμ²μ΄ μλͺ»λμμμ λνλ΄λ μνμ½λ
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}
String fileName = file.getFileName(); // νμΌ λͺ
String filePath = file.getFilePath(); // νμΌ κ²½λ‘
// νμΌ λ€μ΄λ‘λλ₯Ό μν ν€λ μΈν
// - ContentType : application/octet-straem
// - Content-Disposition : attachment; fileanme="νμΌλͺ
.νμ₯μ"
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
// νμΌ μ
λ ₯
File downloadFile = new File(filePath);
FileInputStream fis = new FileInputStream(downloadFile);
ServletOutputStream sos = response.getOutputStream();
// λ€μ΄λ‘λ
FileCopyUtils.copy(fis, sos);
}
/**
* μ΄λ―Έμ§ μΈλ€μΌ
* @param no
* @param response
* @throws Exception
*/
@GetMapping("/img/{no}")
public void showImg(@PathVariable Integer no, HttpServletResponse response) throws Exception {
Files file = fileService.select(no);
String filePath = (file != null) ? file.getFilePath() : null;
Resource resource = resourceLoader.getResource("classpath:static/img/no-image.png");
File imgFile;
if (filePath == null || !(imgFile = new File(filePath)).exists()) {
// νμΌμ΄ μ‘΄μ¬νμ§ μκ±°λ νμΌ κ²½λ‘κ° nullμΈ κ²½μ°
imgFile = resource.getFile();
}
String ext = filePath.substring(filePath.lastIndexOf(".") + 1);
MediaType mType = MediaUtil.getMediaType(ext);
if (mType == null) {
// μ΄λ―Έμ§ νμ
μ΄ μλ κ²½μ°
response.setContentType(MediaType.IMAGE_PNG_VALUE); // κΈ°λ³Έμ μΌλ‘ PNGλ‘ μ€μ
imgFile = resource.getFile();
} else {
// μ΄λ―Έμ§ νμ
μΌ κ²½μ°
response.setContentType(mType.toString());
}
FileInputStream fis = new FileInputStream(imgFile);
ServletOutputStream sos = response.getOutputStream();
FileCopyUtils.copy(fis, sos);
}
/**
* νμΌ μμ
* @param file
* @return
* @throws Exception
*/
@DeleteMapping("/{no}")
public ResponseEntity<String> deleteFile(@PathVariable Integer no) throws Exception {
log.info("[DELETE] - /file");
int fileNo = no;
log.info("fileNo : " + fileNo);
if( fileNo == 0 )
return new ResponseEntity<String>("FAIL", HttpStatus.BAD_REQUEST);
int result = fileService.delete(fileNo);
if( result == 0 )
return new ResponseEntity<String>("FAIL", HttpStatus.OK);
return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
}
}
Java
볡μ¬
React (Front-End)
React λ‘ νμΌ μ
λ‘λ, μ‘°ν, μμ UI λ° API λ₯Ό ꡬνν©λλ€.
νμΌ μ λ‘λ
νμΌ λ±λ‘ UI μΆκ°
BoardInsertForm.jsx
import React, { useState } from 'react'
import { Link } from 'react-router-dom'
import './BoardInsertForm.css'
const BoardInsertForm = ({ onInsert }) => {
// state μ€μ
const [title, setTitle] = useState('');
const [writer, setWriter] = useState('');
const [content, setContent] = useState('');
const [files, setFiles] = useState(null); // β
files state μΆκ°
const handleChangeTitle = (e) => {
setTitle(e.target.value)
}
const handleChangeWriter = (e) => {
setWriter(e.target.value)
}
const handleChangeContent = (e) => {
setContent(e.target.value)
}
// β
νμΌ νΈλ€λ¬ μΆκ°
const handleFileChange = (e) => {
setFiles(e.target.files);
};
const onSubmit = () => {
const formData = new FormData();
formData.append('title', title);
formData.append('writer', writer);
formData.append('content', content);
const headers = {
headers: {
'Content-Type' : 'multipart/form-data',
},
};
if (files) {
for (let i = 0; i < files.length; i++) {
formData.append(`files[${i}]`, files[i]);
}
}
// onInsert(title, writer, content)
// onInsert({title,writer,content,files}, headers) // formData μ¬μ© β
onInsert(formData, headers) // formData μ¬μ© β
}
return (
<div className='container'>
<h1 className='title'>κ²μκΈ λ±λ‘</h1>
<table className='table'>
<tbody>
<tr>
<td>μ λͺ©</td>
<td>
<input type="text"
className='form-input'
value={title}
onChange={handleChangeTitle} />
</td>
</tr>
<tr>
<td>μμ±μ</td>
<td>
<input type="text"
className='form-input'
value={writer}
onChange={handleChangeWriter} />
</td>
</tr>
<tr>
<td colSpan={2}>λ΄μ©</td>
</tr>
<tr>
<td colSpan={2}>
<textarea cols="40" rows="10"
className='form-input'
value={content}
onChange={handleChangeContent}
></textarea>
</td>
</tr>
<tr>
<td>νμΌ</td>
<td>
<input type='file' onChange={handleFileChange} multiple />
</td>
</tr>
</tbody>
</table>
<div className='btn-box'>
<Link to="/boards" className='btn'>λͺ©λ‘</Link>
<button onClick={ onSubmit } className='btn'>λ±λ‘</button>
</div>
</div>
)
}
export default BoardInsertForm
JavaScript
볡μ¬
νμΌ μ λ‘λ μμ² API
files.js
import axios from 'axios';
// μ
λ‘λ
export const upload = (formData, headers) => axios.post(`/file/upload`, formData, headers)
JavaScript
볡μ¬
οΈ νμΌ μ‘°ν
νμΌ λͺ©λ‘ μ‘°ν UI λ° API μΆκ°
BoardReadContainer.jsx
import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import * as boards from '../apis/boards';
import BoardRead from '../components/BoardRead/BoardRead';
// π©βπ» κ²μκΈ μ‘°ν
const BoardReadContainer = () => {
const { no } = useParams()
const [board, setBoard] = useState({});
const [fileList, setFileList] = useState([]);
const [isLoading, setLoading] = useState(false);
const getBoard = async () => {
setLoading(true)
try {
const response = await boards.select(no);
const data = response.data;
console.log(data);
const board = data.board;
const fileList = data.fileList;
setBoard(board);
setFileList(fileList);
}
catch(e) {
console.log(e);
}
setLoading(false)
}
useEffect( () => {
getBoard()
},[])
return (<BoardRead no={no}
board={board}
fileList={fileList}
isLoading={isLoading}
/>)
}
export default BoardReadContainer
JavaScript
볡μ¬
BoardRead.jsx
import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';
import * as format from '../../apis/format';
import './BoardRead.css';
const BoardRead = ({ no, board, fileList, isLoading }) => {
return (
<div className='container'>
<h1 className='title'>κ²μκΈ μ‘°ν</h1>
<h3>λ²νΈ : {no}</h3>
<hr/>
{ isLoading &&
<div>
<img src="/img/loading.webp" alt="loading" />
</div>
}
{ !isLoading && board && (
<table border={1} className='table'>
<tbody>
<tr>
<td>λ²νΈ</td>
<td>
<input type="text" className='form-input' value={board.no} readOnly />
</td>
</tr>
<tr>
<td>λ±λ‘μΌμ</td>
<td>
<input type="text" className='form-input' value={format.formatDate( board.regDate )} readOnly />
</td>
</tr>
<tr>
<td>μ λͺ©</td>
<td>
<input type="text" className='form-input' value={board.title} readOnly />
</td>
</tr>
<tr>
<td>μμ±μ</td>
<td>
<input type="text" className='form-input' value={board.writer} readOnly />
</td>
</tr>
<tr>
<td colSpan={2}>λ΄μ©</td>
</tr>
<tr>
<td colSpan={2}>
<textarea cols="40" rows="10"
className='form-input'
value={board.content}
readOnly></textarea>
</td>
</tr>
<tr>
<td colSpan={2}>νμΌ</td>
</tr>
<tr>
<td colSpan={2}>
{ fileList.map( (file) => (
<div className='file-box' key={file.no}>
<div className="item">
<img src={`/file/img/${file.no}`} alt={file.fileName} />
<span>{file.originName}({ format.byteToUnit(file.fileSize) })</span>
</div>
<div className="item">
</div>
</div>
))}
</td>
</tr>
</tbody>
</table>
)}
<hr />
<div className="btn-box">
<Link className='btn' to="/boards">λͺ©λ‘</Link>
<Link className='btn' to={`/boards/update/${no}`}>μμ </Link>
</div>
</div>
)
}
export default BoardRead
JavaScript
볡μ¬
λ€μ΄λ‘λ UI λ° API μΆκ°
BoardRead.jsx
import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';
import * as format from '../../apis/format';
import './BoardRead.css';
const BoardRead = ({ no, board, fileList, isLoading }) => {
return (
<div className='container'>
<h1 className='title'>κ²μκΈ μ‘°ν</h1>
<h3>λ²νΈ : {no}</h3>
<hr/>
{ isLoading &&
<div>
<img src="/img/loading.webp" alt="loading" />
</div>
}
{ !isLoading && board && (
<table border={1} className='table'>
<tbody>
<tr>
<td>λ²νΈ</td>
<td>
<input type="text" className='form-input' value={board.no} readOnly />
</td>
</tr>
<tr>
<td>λ±λ‘μΌμ</td>
<td>
<input type="text" className='form-input' value={format.formatDate( board.regDate )} readOnly />
</td>
</tr>
<tr>
<td>μ λͺ©</td>
<td>
<input type="text" className='form-input' value={board.title} readOnly />
</td>
</tr>
<tr>
<td>μμ±μ</td>
<td>
<input type="text" className='form-input' value={board.writer} readOnly />
</td>
</tr>
<tr>
<td colSpan={2}>λ΄μ©</td>
</tr>
<tr>
<td colSpan={2}>
<textarea cols="40" rows="10"
className='form-input'
value={board.content}
readOnly></textarea>
</td>
</tr>
<tr>
<td colSpan={2}>νμΌ</td>
</tr>
<tr>
<td colSpan={2}>
{ fileList.map( (file) => (
<div className='file-box' key={file.no}>
<div className="item">
<img src={`/file/img/${file.no}`} alt={file.fileName} />
<span>{file.originName}({ format.byteToUnit(file.fileSize) })</span>
</div>
<div className="item">
<button className="btn" onClick={() => handleDownload(file.no, file.originName)}>λ€μ΄λ‘λ</button>
</div>
</div>
))}
</td>
</tr>
</tbody>
</table>
)}
<hr />
<div className="btn-box">
<Link className='btn' to="/boards">λͺ©λ‘</Link>
<Link className='btn' to={`/boards/update/${no}`}>μμ </Link>
</div>
</div>
)
}
export default BoardRead
JavaScript
볡μ¬
files.js
JavaScript
볡μ¬
μΈλ€μΌ μ΄λ―Έμ§ UI μΆκ°
νμΌ μμ
μμ ν νμΌ μ²΄ν¬λ°μ€ UI μΆκ° λ° μμ μμ² μ, μμ ν νμΌ λ²νΈ 리μ€νΈ λ°μ΄ν° μΆκ°
κ°λ³ νμΌ μμ UI λ° API μΆκ°
κ²μν - νμΌ μ λ‘λ
Spring Boot (Back-End)
Spring Boot λ‘ νμΌ μ
λ‘λ, μ‘°ν, μμ κΈ°λ₯μ ꡬνν©λλ€.
ꡬν κΈ°λ₯
β’
νμΌ μ
λ‘λ
β¦
λ°μ΄ν°λ² μ΄μ€μ λ±λ‘
β¦
νμΌ μμ€ν
μ λ±λ‘
β’
οΈ νμΌ μ‘°ν
β¦
νμΌ λͺ©λ‘ μ‘°ν
β¦
λ€μ΄λ‘λ
β¦
μΈλ€μΌ μ΄λ―Έμ§ 보기
β’
νμΌ μμ
β¦
κ²μκΈμ μ’
μλ μ¬λ¬ νμΌ μμ
β¦
μ ν νμΌ μμ
β¦
κ°λ³ νμΌ μμ
React (Front-End)
React λ‘ νμΌ μ
λ‘λ, μ‘°ν, μμ UI λ° API λ₯Ό ꡬνν©λλ€.
β’
νμΌ μ
λ‘λ
β¦
νμΌ λ±λ‘ UI μΆκ°
β¦
νμΌ μ
λ‘λ μμ² API
β’
οΈ νμΌ μ‘°ν
β¦
νμΌ λͺ©λ‘ μ‘°ν UI λ° API μΆκ°
β¦
λ€μ΄λ‘λ UI λ° API μΆκ°
β¦
μΈλ€μΌ μ΄λ―Έμ§ UI μΆκ°
β’
νμΌ μμ
β¦
κ²μκΈμ μ’
μλ μ¬λ¬ νμΌ μμ (κ²μκΈ μμ μ, λ°±μλμμ μ²λ¦¬ν¨)
β¦
μμ ν νμΌ μ²΄ν¬λ°μ€ UI μΆκ° λ° μμ μμ² μ, μμ ν νμΌ λ²νΈ 리μ€νΈ λ°μ΄ν° μΆκ°
β¦
κ°λ³ νμΌ μμ UI λ° API μΆκ°
Spring Boot (Back-End)
Spring Boot λ‘ νμΌ μ
λ‘λ, μ‘°ν, μμ κΈ°λ₯μ ꡬνν©λλ€.
νμΌ μ λ‘λ
λ°μ΄ν°λ² μ΄μ€μ λ±λ‘
1.
λ°μ΄ν° λ² μ΄μ€ - ν
μ΄λΈ μμ±
2.
SQL 쿼리 Mapper μμ±
3.
DTO
4.
Mapper
5.
Service
6.
Controller
λ°μ΄ν° λ² μ΄μ€ - ν μ΄λΈ μμ±
CREATE TABLE `file` (
`no` int NOT NULL AUTO_INCREMENT, -- νμΌ λ²νΈ (μλμ¦κ°)
`parent_table` varchar(45) NOT NULL, -- λΆλͺ¨ ν
μ΄λΈλͺ
(μ: 'board')
`parent_no` int NOT NULL, -- λΆλͺ¨ ν
μ΄λΈμμμ λ²νΈ
`file_name` text NOT NULL, -- μ μ₯λ νμΌλͺ
`origin_name` text, -- μλ³Έ νμΌλͺ
`file_path` text NOT NULL, -- νμΌ κ²½λ‘
`file_size` int NOT NULL DEFAULT '0', -- νμΌ ν¬κΈ° (κΈ°λ³Έκ° 0)
`reg_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, -- λ±λ‘μΌμ
`upd_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, -- μμ μΌμ
`file_code` int NOT NULL DEFAULT '0', -- νμΌ μ½λ (κΈ°λ³Έκ° 0)
PRIMARY KEY (`no`) -- μ£Όν€ μ€μ
) COMMENT='νμΌ';
SQL
볡μ¬
SQL 쿼리 Mapper μμ±
β’
FileMapper.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">
<!-- namespace="λ§€νΌ μΈν°νμ΄μ€ κ²½λ‘" -->
<mapper namespace="com.joeun.server.mapper.FileMapper">
<!-- νμΌ λͺ©λ‘ -->
<select id="list" resultType="Files">
SELECT *
FROM file
ORDER BY reg_date DESC
</select>
<!-- νμΌ λͺ©λ‘ - λΆλͺ¨ ν
μ΄λΈ κΈ°μ€ -->
<!-- * νμΌμ΄ μ’
μλλ ν
μ΄λΈμ κΈ°μ€μΌλ‘ νμΌ λͺ©λ‘μ μ‘°ν -->
<!-- * κ²μκΈ λ²νΈ 10
π νμΌ λ²νΈ 1
π νμΌ λ²νΈ 2
π νμΌ λ²νΈ 3
-->
<select id="listByParent" resultType="Files">
SELECT *
FROM file
WHERE parent_table = #{parentTable}
AND parent_no = #{parentNo}
ORDER BY reg_date DESC
</select>
<!-- νμΌ μ‘°ν -->
<select id="select" resultType="Files">
SELECT *
FROM file
WHERE no = #{no}
</select>
<!-- νμΌ λ±λ‘ -->
<insert id="insert">
INSERT INTO file( parent_table, parent_no, file_name, origin_name, file_path, file_size, file_code )
VALUES ( #{parentTable}, #{parentNo}, #{fileName}, #{originName}, #{filePath}, #{fileSize}, #{fileCode} )
</insert>
<!-- νμΌ μμ -->
<update id="update">
UPDATE file
SET parent_table = #{parentTable}
,parent_no = #{parentNo}
,file_name = #{fileName}
,origin_name = #{originName}
,file_path = #{filePath}
,file_size = #{fileSize}
,file_code = #{fileCode}
WHERE no = #{no}
</update>
<!-- νμΌ μμ -->
<delete id="delete">
DELETE FROM file
WHERE no = #{no}
</delete>
<!-- νμΌ λͺ©λ‘ μμ - λΆλͺ¨ ν
μ΄λΈ κΈ°μ€ νμΌ λͺ©λ‘ μμ -->
<delete id="deleteByParent">
DELETE FROM file
WHERE parent_table = #{parentTable}
AND parent_no = #{parentNo}
</delete>
<!-- κ²μκΈ λ²νΈ μ΅λκ° -->
<select id="maxPk" resultType="int">
SELECT MAX(no)
FROM file
</select>
</mapper>
SQL
볡μ¬
DTO
β’
Files.java
package com.joeun.server.dto;
import java.util.Date;
import lombok.Data;
@Data
public class Files {
private int no;
private String parentTable;
private int parentNo;
private String fileName;
private String originName;
private String filePath;
private long fileSize;
private Date regDate;
private Date updDate;
private int fileCode;
}
Java
볡μ¬
Mapper
β’
FileMapper.java
package com.joeun.server.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.joeun.server.dto.Files;
@Mapper
public interface FileMapper {
// νμΌ λͺ©λ‘
public List<Files> list() throws Exception;
// νμΌ μ‘°ν
public Files select(int no) throws Exception;
// νμΌ λ±λ‘
public int insert(Files file) throws Exception;
// νμΌ μμ
public int update(Files file) throws Exception;
// νμΌ μμ
public int delete(int no) throws Exception;
// νμΌ λ²νΈ(κΈ°λ³Έν€) μ΅λκ°
public int maxPk() throws Exception;
// νμΌ λͺ©λ‘ - λΆλͺ¨ κΈ°μ€
public List<Files> listByParent(Files file) throws Exception;
// νμΌ μμ - λΆλͺ¨ κΈ°μ€
public int deleteByParent(Files file) throws Exception;
}
Java
볡μ¬
Service
β’
FileService.java
β’
FileServiceImpl.java
β’
BoardServiceImpl.java
β’
FileService.java
package com.joeun.server.service;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import jakarta.servlet.http.HttpServletResponse;
public interface FileService {
// νμΌ λͺ©λ‘
public List<Files> list() throws Exception;
// νμΌ μ‘°ν
public Files select(int no) throws Exception;
// νμΌ λ±λ‘
public int insert(Files file) throws Exception;
// νμΌ μμ
public int update(Files file) throws Exception;
// νμΌ μ
λ‘λ
public int uploadFiles(Files file, List<MultipartFile> fileList) throws Exception;
// νμΌ μ
λ‘λ
public int upload(Files file) throws Exception;
}
Java
볡μ¬
β’
FileServiceImpl.java
package com.joeun.server.service;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.FileMapper;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class FileServiceImpl implements FileService {
@Autowired
private FileMapper fileMapper;
@Value("${upload.path}") // application.properties μ μ€μ ν μ
λ‘λ κ²½λ‘ μμ±λͺ
private String uploadPath; // μ
λ‘λ κ²½λ‘
@Override
public List<Files> list() throws Exception {
List<Files> fileList = fileMapper.list();
return fileList;
}
@Override
public Files select(int no) throws Exception {
Files file = fileMapper.select(no);
return file;
}
@Override
public int insert(Files file) throws Exception {
int result = fileMapper.insert(file);
return result;
}
@Override
public int update(Files file) throws Exception {
int result = fileMapper.update(file);
return result;
}
@Override
public int uploadFiles(Files fileInfo, List<MultipartFile> fileList) throws Exception {
int result = 0;
for (MultipartFile file : fileList) {
result += uploadFile( fileInfo, file );
}
log.info(result + "κ° νμΌμ μ
λ‘λνμμ΅λλ€.");
return result;
}
@Override
@Transactional
public int upload(Files file) throws Exception {
int result = uploadFile(file, file.getFile());
if( result > 0 )
result = fileMapper.maxPk();
return result;
}
public int uploadFile(Files fileInfo, MultipartFile file) throws Exception {
int result = 0;
if( file.isEmpty() ) return result;
// νμΌ μ 보 : μλ³ΈνμΌλͺ
, νμΌ μ©λ, νμΌ λ°μ΄ν°
String originName = file.getOriginalFilename();
long fileSize = file.getSize();
// μ
λ‘λ κ²½λ‘
// νμΌλͺ
μ€λ³΅ λ°©μ§ λ°©λ²(μ μ±
)
// - λ μ§_νμΌλͺ
.νμ₯μ
// - UID_νμΌλͺ
.νμ₯μ
// UID_κ°μμ§.png
String fileName = UUID.randomUUID().toString() + "_" + originName;
// c:/upload/UID_κ°μμ§.png
String filePath = uploadPath + "/" + fileName;
// - DB μ νμΌ μ 보 λ±λ‘
Files uploadedFile = new Files();
uploadedFile.setParentTable(fileInfo.getParentTable());
uploadedFile.setParentNo(fileInfo.getParentNo());
uploadedFile.setFileName(fileName);
uploadedFile.setFilePath(filePath);
uploadedFile.setOriginName(originName);
uploadedFile.setFileSize(fileSize);
uploadedFile.setFileCode(0);
// DB μ λ°μ΄ν° λ±λ‘
result = fileMapper.insert(uploadedFile);
return result;
}
}
Java
볡μ¬
β’
BoardServiceImpl.java
package com.joeun.server.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Board;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.BoardMapper;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class BoardServiceImpl implements BoardService {
@Autowired
private BoardMapper boardMapper;
@Autowired
private FileService fileService;
@Override
public List<Board> list() throws Exception {
List<Board> boardList = boardMapper.list();
return boardList;
}
@Override
public Board select(int no) throws Exception {
Board board = boardMapper.select(no);
return board;
}
@Override
@Transactional
public int insert(Board board) throws Exception {
int result = boardMapper.insert(board); // μλ‘ μμ±λ λ°μ΄ν°μ pk κ°μ Έμ΄
int parentNo = boardMapper.maxPk();
board.setNo(parentNo);
// β
(New) νμΌ μ
λ‘λ
result += uploadFiles(board);
return result;
}
@Override
public int update(Board board) throws Exception {
int result = boardMapper.update(board);
// νμΌ μ
λ‘λ
result += uploadFiles(board);
return result;
}
@Override
public int delete(int no) throws Exception {
int result = boardMapper.delete(no);
return result;
}
@Override
public int updateViews(int count, int no) throws Exception {
int result = boardMapper.updateViews(count, no);
return result;
}
// β
(New) νμΌ μ
λ‘λ
public int uploadFiles(Board board) throws Exception {
String parentTable = "board";
int parentNo = board.getNo();
int result = 0;
List<MultipartFile> fileList = board.getFiles();
if( fileList != null && !fileList.isEmpty() ) {
Files fileInfo = new Files();
fileInfo.setParentTable(parentTable);
fileInfo.setParentNo(parentNo);
result = fileService.uploadFiles(fileInfo, fileList);
}
return result;
}
}
Java
볡μ¬
Controller
β’
FileController.java
package com.joeun.server.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
@RequestMapping("/file")
public class FileController {
}
Java
볡μ¬
νμΌ μμ€ν μ λ±λ‘
1.
DTO
2.
Service
DTO
β’
Files.java
package com.joeun.server.dto;
import java.util.Date;
import org.springframework.web.multipart.MultipartFile;
import lombok.Data;
@Data
public class Files {
private int no;
private String parentTable;
private int parentNo;
private String fileName;
private String originName;
private String filePath;
private long fileSize;
private Date regDate;
private Date updDate;
private int fileCode;
MultipartFile file; // β
μΆκ°
}
Java
볡μ¬
Service
β’
FileServiceImpl.java
μΆκ°ν μ½λ
// β
(New) νμΌμ
λ‘λ
// - μλ² μΈ‘, νμΌ μμ€ν
μ νμΌ λ³΅μ¬
File uploadFile = new File(uploadPath, fileName);
FileCopyUtils.copy(fileData, uploadFile); // νμΌ μ
λ‘λ
Java
볡μ¬
package com.joeun.server.service;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.FileMapper;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class FileServiceImpl implements FileService {
@Autowired
private FileMapper fileMapper;
@Value("${upload.path}") // application.properties μ μ€μ ν μ
λ‘λ κ²½λ‘ μμ±λͺ
private String uploadPath; // μ
λ‘λ κ²½λ‘
@Override
public List<Files> list() throws Exception {
List<Files> fileList = fileMapper.list();
return fileList;
}
@Override
public Files select(int no) throws Exception {
Files file = fileMapper.select(no);
return file;
}
@Override
public int insert(Files file) throws Exception {
int result = fileMapper.insert(file);
return result;
}
@Override
public int update(Files file) throws Exception {
int result = fileMapper.update(file);
return result;
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
@Override
public int uploadFiles(Files fileInfo, List<MultipartFile> fileList) throws Exception {
int result = 0;
for (MultipartFile file : fileList) {
result += uploadFile( fileInfo, file);
}
log.info(result + "κ° νμΌμ μ
λ‘λνμμ΅λλ€.");
return result;
}
@Override
public int deleteByNoList(List<Integer> deleteFileNoList) throws Exception {
int result = 0;
if( deleteFileNoList != null && !deleteFileNoList.isEmpty() )
for (Integer deleteFileNo : deleteFileNoList) {
if( deleteFileNo == null ) continue;
fileMapper.delete(deleteFileNo);
log.info(deleteFileNo + "λ² νμΌ μμ ");
result++;
}
return result;
}
@Override
@Transactional
public int upload(Files file) throws Exception {
int result = uploadFile(file, file.getFile());
if( result > 0 )
result = fileMapper.maxPk();
return result;
}
public int uploadFile(Files fileInfo, MultipartFile file) throws Exception {
int result = 0;
if( file.isEmpty() ) return result;
// νμΌ μ 보 : μλ³ΈνμΌλͺ
, νμΌ μ©λ, νμΌ λ°μ΄ν°
String originName = file.getOriginalFilename();
long fileSize = file.getSize();
byte[] fileData = file.getBytes();
// μ
λ‘λ κ²½λ‘
// νμΌλͺ
μ€λ³΅ λ°©μ§ λ°©λ²(μ μ±
)
// - λ μ§_νμΌλͺ
.νμ₯μ
// - UID_νμΌλͺ
.νμ₯μ
// UID_κ°μμ§.png
String fileName = UUID.randomUUID().toString() + "_" + originName;
// c:/upload/UID_κ°μμ§.png
String filePath = uploadPath + "/" + fileName;
// β
(New) νμΌμ
λ‘λ
// - μλ² μΈ‘, νμΌ μμ€ν
μ νμΌ λ³΅μ¬
File uploadFile = new File(uploadPath, fileName);
FileCopyUtils.copy(fileData, uploadFile); // νμΌ μ
λ‘λ
// - DB μ νμΌ μ 보 λ±λ‘
Files uploadedFile = new Files();
uploadedFile.setParentTable(fileInfo.getParentTable());
uploadedFile.setParentNo(fileInfo.getParentNo());
uploadedFile.setFileName(fileName);
uploadedFile.setFilePath(filePath);
uploadedFile.setOriginName(originName);
uploadedFile.setFileSize(fileSize);
uploadedFile.setFileCode(0);
result = fileMapper.insert(uploadedFile);
return result;
}
}
Java
볡μ¬
οΈ νμΌ μ‘°ν
νμΌ λͺ©λ‘ μ‘°ν
β’
FileService.java
β’
FileServiceImpl.java
β’
BoardServiceImpl.java
β’
BoardController.java
FileService.java
package com.joeun.server.service;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import jakarta.servlet.http.HttpServletResponse;
public interface FileService {
// νμΌ λͺ©λ‘
public List<Files> list() throws Exception;
// νμΌ μ‘°ν
public Files select(int no) throws Exception;
// νμΌ λ±λ‘
public int insert(Files file) throws Exception;
// νμΌ μμ
public int update(Files file) throws Exception;
// νμΌ μ
λ‘λ
public int uploadFiles(Files file, List<MultipartFile> fileList) throws Exception;
// νμΌ μ
λ‘λ
public int upload(Files file) throws Exception;
// β
(New) νμΌ λͺ©λ‘ - λΆλͺ¨ κΈ°μ€
public List<Files> listByParent(Files file) throws Exception;
}
Java
볡μ¬
FileServiceImpl.java
package com.joeun.server.service;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.FileMapper;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class FileServiceImpl implements FileService {
@Autowired
private FileMapper fileMapper;
@Value("${upload.path}") // application.properties μ μ€μ ν μ
λ‘λ κ²½λ‘ μμ±λͺ
private String uploadPath; // μ
λ‘λ κ²½λ‘
@Override
public List<Files> list() throws Exception {
List<Files> fileList = fileMapper.list();
return fileList;
}
@Override
public Files select(int no) throws Exception {
Files file = fileMapper.select(no);
return file;
}
@Override
public int insert(Files file) throws Exception {
int result = fileMapper.insert(file);
return result;
}
@Override
public int update(Files file) throws Exception {
int result = fileMapper.update(file);
return result;
}
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
@Override
public int uploadFiles(Files fileInfo, List<MultipartFile> fileList) throws Exception {
int result = 0;
for (MultipartFile file : fileList) {
result += uploadFile( fileInfo, file);
}
log.info(result + "κ° νμΌμ μ
λ‘λνμμ΅λλ€.");
return result;
}
@Override
public int deleteByNoList(List<Integer> deleteFileNoList) throws Exception {
int result = 0;
if( deleteFileNoList != null && !deleteFileNoList.isEmpty() )
for (Integer deleteFileNo : deleteFileNoList) {
if( deleteFileNo == null ) continue;
fileMapper.delete(deleteFileNo);
log.info(deleteFileNo + "λ² νμΌ μμ ");
result++;
}
return result;
}
@Override
@Transactional
public int upload(Files file) throws Exception {
int result = uploadFile(file, file.getFile());
if( result > 0 )
result = fileMapper.maxPk();
return result;
}
public int uploadFile(Files fileInfo, MultipartFile file) throws Exception {
int result = 0;
if( file.isEmpty() ) return result;
// νμΌ μ 보 : μλ³ΈνμΌλͺ
, νμΌ μ©λ, νμΌ λ°μ΄ν°
String originName = file.getOriginalFilename();
long fileSize = file.getSize();
byte[] fileData = file.getBytes();
// μ
λ‘λ κ²½λ‘
// νμΌλͺ
μ€λ³΅ λ°©μ§ λ°©λ²(μ μ±
)
// - λ μ§_νμΌλͺ
.νμ₯μ
// - UID_νμΌλͺ
.νμ₯μ
// UID_κ°μμ§.png
String fileName = UUID.randomUUID().toString() + "_" + originName;
// c:/upload/UID_κ°μμ§.png
String filePath = uploadPath + "/" + fileName;
// - μλ² μΈ‘, νμΌ μμ€ν
μ νμΌ λ³΅μ¬
File uploadFile = new File(uploadPath, fileName);
FileCopyUtils.copy(fileData, uploadFile); // νμΌ μ
λ‘λ
// - DB μ νμΌ μ 보 λ±λ‘
Files uploadedFile = new Files();
uploadedFile.setParentTable(fileInfo.getParentTable());
uploadedFile.setParentNo(fileInfo.getParentNo());
uploadedFile.setFileName(fileName);
uploadedFile.setFilePath(filePath);
uploadedFile.setOriginName(originName);
uploadedFile.setFileSize(fileSize);
uploadedFile.setFileCode(0);
result = fileMapper.insert(uploadedFile);
return result;
}
// β
(New) - νμΌ λͺ©λ‘ μ‘°ν
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
}
Java
볡μ¬
BoardController.java
μΆκ°ν μ½λ
@GetMapping("/{no}")
public ResponseEntity<?> getOne(@PathVariable Integer no, Files files) {
log.info("[GET] - /boards/" + no + " - κ²μκΈ μ‘°ν");
try {
Board board = boardService.select(no);
files.setParentTable("board");
files.setParentNo(no);
List<Files> fileList = fileService.listByParent(files); // νμΌ μ 보
Map<String, Object> response = new HashMap<>();
response.put("board", board);
response.put("fileList", fileList);
if( board == null ) {
board = new Board();
board.setTitle("λ°μ΄ν° μμ");
}
return new ResponseEntity<>(response, HttpStatus.OK);
} catch (Exception e) {
log.error(null, e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Java
볡μ¬
package com.joeun.server.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Board;
import com.joeun.server.dto.Files;
import com.joeun.server.service.BoardService;
import com.joeun.server.service.FileService;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestController
@RequestMapping("/boards")
public class BoardController {
@Autowired
private BoardService boardService;
@Autowired
private FileService fileService;
// π©βπ» CRUD λ©μλ μλ μμ± : sp-crud
// π©βπ» μλ import : alt + shift + O
// π©βπ» ν μ€ μμ : ctrl + shift + K
@GetMapping()
public ResponseEntity<?> getAll() {
log.info("[GET] - /boards - κ²μκΈ λͺ©λ‘");
try {
List<Board> boardList = boardService.list();
if( boardList == null )
log.info("μ‘°νλ κ²μκΈ μμ");
else
log.info("κ²μκΈ μ : " + boardList.size());
return new ResponseEntity<>(boardList, HttpStatus.OK);
} catch (Exception e) {
log.error(null, e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@GetMapping("/{no}")
public ResponseEntity<?> getOne(@PathVariable Integer no, Files files) {
log.info("[GET] - /boards/" + no + " - κ²μκΈ μ‘°ν");
try {
Board board = boardService.select(no);
files.setParentTable("board");
files.setParentNo(no);
List<Files> fileList = fileService.listByParent(files); // νμΌ μ 보
Map<String, Object> response = new HashMap<>();
response.put("board", board);
response.put("fileList", fileList);
if( board == null ) {
board = new Board();
board.setTitle("λ°μ΄ν° μμ");
}
return new ResponseEntity<>(response, HttpStatus.OK);
} catch (Exception e) {
log.error(null, e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PostMapping()
// public ResponseEntity<?> create(@RequestBody Board board) { // Content-Type : application/json
public ResponseEntity<?> create(Board board) { // Content-Type : multipart/form-data
log.info("[POST] - /boards - κ²μκΈ λ±λ‘");
log.info("board : " + board.toString());
List<MultipartFile> files = board.getFiles();
if( files != null )
for (MultipartFile file : files) {
log.info("file : " + file.getOriginalFilename());
}
try {
int result = boardService.insert(board);
if( result > 0 )
return new ResponseEntity<>("κ²μκΈ λ±λ‘ μλ£", HttpStatus.CREATED); // 201
else
return new ResponseEntity<>("κ²μκΈ λ±λ‘ μ€ν¨", HttpStatus.OK);
} catch (Exception e) {
log.error(null, e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PutMapping()
// public ResponseEntity<?> update(@RequestBody Board board) { // Content-Type : application/json
public ResponseEntity<?> update(Board board) { // Content-Type : multipart/form-data
log.info("[PUT] - /boards - κ²μκΈ μμ ");
try {
int result = boardService.update(board);
log.info("μμ : " + board);
if( result > 0 )
return new ResponseEntity<>("κ²μκΈ μμ μλ£", HttpStatus.OK);
else
return new ResponseEntity<>("κ²μκΈ μμ μ€ν¨", HttpStatus.OK);
} catch (Exception e) {
log.error(null, e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@DeleteMapping("/{no}")
public ResponseEntity<?> destroy(@PathVariable Integer no) {
log.info("[DELETE] - /boards/" + no + " - κ²μκΈ μμ ");
try {
int result = boardService.delete(no);
if( result > 0 )
return new ResponseEntity<>("κ²μκΈ μμ μλ£", HttpStatus.OK);
else
return new ResponseEntity<>("κ²μκΈ μμ μ€ν¨", HttpStatus.OK);
} catch (Exception e) {
log.error(null, e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
Java
볡μ¬
λ€μ΄λ‘λ
β’
FileService.java
β’
FileServiceImpl.java
β’
FileController.java
FileService.java
package com.joeun.server.service;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import jakarta.servlet.http.HttpServletResponse;
public interface FileService {
// νμΌ λͺ©λ‘
public List<Files> list() throws Exception;
// νμΌ μ‘°ν
public Files select(int no) throws Exception;
// νμΌ λ±λ‘
public int insert(Files file) throws Exception;
// νμΌ μμ
public int update(Files file) throws Exception;
// νμΌ μ
λ‘λ
public int uploadFiles(Files file, List<MultipartFile> fileList) throws Exception;
// νμΌ μ
λ‘λ
public int upload(Files file) throws Exception;
// νμΌ λͺ©λ‘ - λΆλͺ¨ κΈ°μ€
public List<Files> listByParent(Files file) throws Exception;
// β
(New) - νμΌ λ€μ΄λ‘λ
public int download(int no, HttpServletResponse response) throws Exception;
}
Java
볡μ¬
FileServiceImpl.java
package com.joeun.server.service;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.FileMapper;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class FileServiceImpl implements FileService {
@Autowired
private FileMapper fileMapper;
@Value("${upload.path}") // application.properties μ μ€μ ν μ
λ‘λ κ²½λ‘ μμ±λͺ
private String uploadPath; // μ
λ‘λ κ²½λ‘
@Override
public List<Files> list() throws Exception {
List<Files> fileList = fileMapper.list();
return fileList;
}
@Override
public Files select(int no) throws Exception {
Files file = fileMapper.select(no);
return file;
}
@Override
public int insert(Files file) throws Exception {
int result = fileMapper.insert(file);
return result;
}
@Override
public int update(Files file) throws Exception {
int result = fileMapper.update(file);
return result;
}
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
@Override
public int uploadFiles(Files fileInfo, List<MultipartFile> fileList) throws Exception {
int result = 0;
for (MultipartFile file : fileList) {
result += uploadFile( fileInfo, file);
}
log.info(result + "κ° νμΌμ μ
λ‘λνμμ΅λλ€.");
return result;
}
@Override
public int deleteByNoList(List<Integer> deleteFileNoList) throws Exception {
int result = 0;
if( deleteFileNoList != null && !deleteFileNoList.isEmpty() )
for (Integer deleteFileNo : deleteFileNoList) {
if( deleteFileNo == null ) continue;
fileMapper.delete(deleteFileNo);
log.info(deleteFileNo + "λ² νμΌ μμ ");
result++;
}
return result;
}
@Override
@Transactional
public int upload(Files file) throws Exception {
int result = uploadFile(file, file.getFile());
if( result > 0 )
result = fileMapper.maxPk();
return result;
}
public int uploadFile(Files fileInfo, MultipartFile file) throws Exception {
int result = 0;
if( file.isEmpty() ) return result;
// νμΌ μ 보 : μλ³ΈνμΌλͺ
, νμΌ μ©λ, νμΌ λ°μ΄ν°
String originName = file.getOriginalFilename();
long fileSize = file.getSize();
byte[] fileData = file.getBytes();
// μ
λ‘λ κ²½λ‘
// νμΌλͺ
μ€λ³΅ λ°©μ§ λ°©λ²(μ μ±
)
// - λ μ§_νμΌλͺ
.νμ₯μ
// - UID_νμΌλͺ
.νμ₯μ
// UID_κ°μμ§.png
String fileName = UUID.randomUUID().toString() + "_" + originName;
// c:/upload/UID_κ°μμ§.png
String filePath = uploadPath + "/" + fileName;
// - μλ² μΈ‘, νμΌ μμ€ν
μ νμΌ λ³΅μ¬
File uploadFile = new File(uploadPath, fileName);
FileCopyUtils.copy(fileData, uploadFile); // νμΌ μ
λ‘λ
// - DB μ νμΌ μ 보 λ±λ‘
Files uploadedFile = new Files();
uploadedFile.setParentTable(fileInfo.getParentTable());
uploadedFile.setParentNo(fileInfo.getParentNo());
uploadedFile.setFileName(fileName);
uploadedFile.setFilePath(filePath);
uploadedFile.setOriginName(originName);
uploadedFile.setFileSize(fileSize);
uploadedFile.setFileCode(0);
result = fileMapper.insert(uploadedFile);
return result;
}
// νμΌ λͺ©λ‘ μ‘°ν
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int download(int fileNo, HttpServletResponse response) throws Exception {
// result
// 0 : νμΌ λ€μ΄λ‘λ μ²λ¦¬ μ€ν¨
// 1 : νμΌ λ€μ΄λ‘λ μ±κ³΅
Files file = fileMapper.select(fileNo);
if( file == null ) {
// BAD_REQUEST : 400, ν΄λΌμ΄μΈνΈμ μμ²μ΄ μλͺ»λμμμ μλ €μ£Όλ μνμ½λ
// response.setStatus(response.SC_BAD_REQUEST);
return 0;
}
String filePath = file.getFilePath(); // νμΌ κ²½λ‘
String fileName = file.getFileName(); // νμΌ μ΄λ¦
// λ€μ΄λ‘λ μλ΅μ μν ν€λ μΈν
// - ContentType : application/octet-stream
// - Content-Disposition : attachment, filename="νμΌλͺ
.νμ₯μ"
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
// νμΌ λ€μ΄λ‘λ
// - νμΌ μ
λ ₯
File downloadFile = new File(filePath);
FileInputStream fis = new FileInputStream(downloadFile);
// - νμΌ μΆλ ₯
ServletOutputStream sos = response.getOutputStream();
// λ€μ΄λ‘λ
FileCopyUtils.copy(fis, sos);
fis.close();
sos.close();
return 1;
}
}
Java
볡μ¬
FileController.java
package com.joeun.server.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
@RequestMapping("/file")
public class FileController {
@Autowired
private FileService fileService;
/**
* νμΌ λ€μ΄λ‘λ
* @param fileNo
* @param response
* @throws Exception
*/
@GetMapping("/{no}")
public void fileDownload(@PathVariable("no") int no
,HttpServletResponse response) throws Exception {
// νμΌ μ‘°ν
Files file = fileService.select(no);
// νμΌμ΄ μ‘΄μ¬νμ§ μμΌλ©΄,
if( file == null ) {
// μλ΅ μνμ½λ : 400, ν΄λΌμ΄μΈνΈμ μμ²μ΄ μλͺ»λμμμ λνλ΄λ μνμ½λ
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}
String fileName = file.getFileName(); // νμΌ λͺ
String filePath = file.getFilePath(); // νμΌ κ²½λ‘
// νμΌ λ€μ΄λ‘λλ₯Ό μν ν€λ μΈν
// - ContentType : application/octet-straem
// - Content-Disposition : attachment; fileanme="νμΌλͺ
.νμ₯μ"
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
// νμΌ μ
λ ₯
File downloadFile = new File(filePath);
FileInputStream fis = new FileInputStream(downloadFile);
ServletOutputStream sos = response.getOutputStream();
// λ€μ΄λ‘λ
FileCopyUtils.copy(fis, sos);
}
}
Java
볡μ¬
μΈλ€μΌ μ΄λ―Έμ§ 보기
β’
FileController.java
FileController.java
package com.joeun.server.controller;
import java.io.File;
import java.io.FileInputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.joeun.server.dto.Files;
import com.joeun.server.service.FileService;
import com.joeun.server.utils.MediaUtil;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
@RequestMapping("/file")
public class FileController {
@Autowired
private FileService fileService;
@Autowired
private ResourceLoader resourceLoader;
/**
* νμΌ λ€μ΄λ‘λ
* @param fileNo
* @param response
* @throws Exception
*/
@GetMapping("/{no}")
public void fileDownload(@PathVariable("no") int no
,HttpServletResponse response) throws Exception {
// νμΌ μ‘°ν
Files file = fileService.select(no);
// νμΌμ΄ μ‘΄μ¬νμ§ μμΌλ©΄,
if( file == null ) {
// μλ΅ μνμ½λ : 400, ν΄λΌμ΄μΈνΈμ μμ²μ΄ μλͺ»λμμμ λνλ΄λ μνμ½λ
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}
String fileName = file.getFileName(); // νμΌ λͺ
String filePath = file.getFilePath(); // νμΌ κ²½λ‘
// νμΌ λ€μ΄λ‘λλ₯Ό μν ν€λ μΈν
// - ContentType : application/octet-straem
// - Content-Disposition : attachment; fileanme="νμΌλͺ
.νμ₯μ"
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
// νμΌ μ
λ ₯
File downloadFile = new File(filePath);
FileInputStream fis = new FileInputStream(downloadFile);
ServletOutputStream sos = response.getOutputStream();
// λ€μ΄λ‘λ
FileCopyUtils.copy(fis, sos);
}
/**
* μ΄λ―Έμ§ μΈλ€μΌ
* @param no
* @param response
* @throws Exception
*/
@GetMapping("/img/{no}")
public void showImg(@PathVariable Integer no, HttpServletResponse response) throws Exception {
Files file = fileService.select(no);
String filePath = (file != null) ? file.getFilePath() : null;
Resource resource = resourceLoader.getResource("classpath:static/img/no-image.png");
File imgFile;
if (filePath == null || !(imgFile = new File(filePath)).exists()) {
// νμΌμ΄ μ‘΄μ¬νμ§ μκ±°λ νμΌ κ²½λ‘κ° nullμΈ κ²½μ°
imgFile = resource.getFile();
}
String ext = filePath.substring(filePath.lastIndexOf(".") + 1);
MediaType mType = MediaUtil.getMediaType(ext);
if (mType == null) {
// μ΄λ―Έμ§ νμ
μ΄ μλ κ²½μ°
response.setContentType(MediaType.IMAGE_PNG_VALUE); // κΈ°λ³Έμ μΌλ‘ PNGλ‘ μ€μ
imgFile = resource.getFile();
} else {
// μ΄λ―Έμ§ νμ
μΌ κ²½μ°
response.setContentType(mType.toString());
}
FileInputStream fis = new FileInputStream(imgFile);
ServletOutputStream sos = response.getOutputStream();
FileCopyUtils.copy(fis, sos);
}
}
Java
볡μ¬
νμΌ μμ
κ²μκΈμ μ’ μλ μ¬λ¬ νμΌ μμ
β’
FileService.java
β’
FileServiceImpl.java
β’
BoardServiceImpl.java
β’
FileService.java
package com.joeun.server.service;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import jakarta.servlet.http.HttpServletResponse;
public interface FileService {
// νμΌ λͺ©λ‘
public List<Files> list() throws Exception;
// νμΌ μ‘°ν
public Files select(int no) throws Exception;
// νμΌ λ±λ‘
public int insert(Files file) throwsdeleteByParent Exception;
// νμΌ μμ
public int update(Files file) throws Exception;
// νμΌ μμ
public int delete(int no) throws Exception;
// νμΌ μ
λ‘λ
public int uploadFiles(Files file, List<MultipartFile> fileList) throws Exception;
// νμΌ μ
λ‘λ
public int upload(Files file) throws Exception;
// νμΌ λͺ©λ‘ - λΆλͺ¨ κΈ°μ€
public List<Files> listByParent(Files file) throws Exception;
// νμΌ λ€μ΄λ‘λ
public int download(int no, HttpServletResponse response) throws Exception;
// β
(New) νμΌ μμ - λΆλͺ¨ κΈ°μ€
public int deleteByParent(Files fileInfo) throws Exception;
}
Java
볡μ¬
β’
FileServiceImpl.java
μΆκ°ν μ½λ
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
Java
볡μ¬
package com.joeun.server.service;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.FileMapper;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class FileServiceImpl implements FileService {
@Autowired
private FileMapper fileMapper;
@Value("${upload.path}") // application.properties μ μ€μ ν μ
λ‘λ κ²½λ‘ μμ±λͺ
private String uploadPath; // μ
λ‘λ κ²½λ‘
@Override
public List<Files> list() throws Exception {
List<Files> fileList = fileMapper.list();
return fileList;
}
@Override
public Files select(int no) throws Exception {
Files file = fileMapper.select(no);
return file;
}
@Override
public int insert(Files file) throws Exception {
int result = fileMapper.insert(file);
return result;
}
@Override
public int update(Files file) throws Exception {
int result = fileMapper.update(file);
return result;
}
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
@Override
public int uploadFiles(Files fileInfo, List<MultipartFile> fileList) throws Exception {
int result = 0;
for (MultipartFile file : fileList) {
result += uploadFile( fileInfo, file);
}
log.info(result + "κ° νμΌμ μ
λ‘λνμμ΅λλ€.");
return result;
}
@Override
public int deleteByNoList(List<Integer> deleteFileNoList) throws Exception {
int result = 0;
if( deleteFileNoList != null && !deleteFileNoList.isEmpty() )
for (Integer deleteFileNo : deleteFileNoList) {
if( deleteFileNo == null ) continue;
fileMapper.delete(deleteFileNo);
log.info(deleteFileNo + "λ² νμΌ μμ ");
result++;
}
return result;
}
@Override
@Transactional
public int upload(Files file) throws Exception {
int result = uploadFile(file, file.getFile());
if( result > 0 )
result = fileMapper.maxPk();
return result;
}
public int uploadFile(Files fileInfo, MultipartFile file) throws Exception {
int result = 0;
if( file.isEmpty() ) return result;
// νμΌ μ 보 : μλ³ΈνμΌλͺ
, νμΌ μ©λ, νμΌ λ°μ΄ν°
String originName = file.getOriginalFilename();
long fileSize = file.getSize();
byte[] fileData = file.getBytes();
// μ
λ‘λ κ²½λ‘
// νμΌλͺ
μ€λ³΅ λ°©μ§ λ°©λ²(μ μ±
)
// - λ μ§_νμΌλͺ
.νμ₯μ
// - UID_νμΌλͺ
.νμ₯μ
// UID_κ°μμ§.png
String fileName = UUID.randomUUID().toString() + "_" + originName;
// c:/upload/UID_κ°μμ§.png
String filePath = uploadPath + "/" + fileName;
// - μλ² μΈ‘, νμΌ μμ€ν
μ νμΌ λ³΅μ¬
File uploadFile = new File(uploadPath, fileName);
FileCopyUtils.copy(fileData, uploadFile); // νμΌ μ
λ‘λ
// - DB μ νμΌ μ 보 λ±λ‘
Files uploadedFile = new Files();
uploadedFile.setParentTable(fileInfo.getParentTable());
uploadedFile.setParentNo(fileInfo.getParentNo());
uploadedFile.setFileName(fileName);
uploadedFile.setFilePath(filePath);
uploadedFile.setOriginName(originName);
uploadedFile.setFileSize(fileSize);
uploadedFile.setFileCode(0);
result = fileMapper.insert(uploadedFile);
return result;
}
// νμΌ λͺ©λ‘ μ‘°ν
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int download(int fileNo, HttpServletResponse response) throws Exception {
// result
// 0 : νμΌ λ€μ΄λ‘λ μ²λ¦¬ μ€ν¨
// 1 : νμΌ λ€μ΄λ‘λ μ±κ³΅
Files file = fileMapper.select(fileNo);
if( file == null ) {
// BAD_REQUEST : 400, ν΄λΌμ΄μΈνΈμ μμ²μ΄ μλͺ»λμμμ μλ €μ£Όλ μνμ½λ
// response.setStatus(response.SC_BAD_REQUEST);
return 0;
}
String filePath = file.getFilePath(); // νμΌ κ²½λ‘
String fileName = file.getFileName(); // νμΌ μ΄λ¦
// λ€μ΄λ‘λ μλ΅μ μν ν€λ μΈν
// - ContentType : application/octet-stream
// - Content-Disposition : attachment, filename="νμΌλͺ
.νμ₯μ"
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
// νμΌ λ€μ΄λ‘λ
// - νμΌ μ
λ ₯
File downloadFile = new File(filePath);
FileInputStream fis = new FileInputStream(downloadFile);
// - νμΌ μΆλ ₯
ServletOutputStream sos = response.getOutputStream();
// λ€μ΄λ‘λ
FileCopyUtils.copy(fis, sos);
fis.close();
sos.close();
return 1;
}
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
}
Java
볡μ¬
β’
BoardServiceImpl.java
μΆκ°ν μ½λ
@Override
@Transactional
public int delete(int no) throws Exception {
int result = boardMapper.delete(no);
String parentTable = "board";
int parentNo = no;
if( result > 0 ) {
Files fileInfo = new Files();
fileInfo.setParentTable(parentTable);
fileInfo.setParentNo(parentNo);
int fileResult = fileService.deleteByParent(fileInfo);
result = fileResult;
}
return result;
}
Java
볡μ¬
package com.joeun.server.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Board;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.BoardMapper;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class BoardServiceImpl implements BoardService {
@Autowired
private BoardMapper boardMapper;
@Autowired
private FileService fileService;
@Override
public List<Board> list() throws Exception {
List<Board> boardList = boardMapper.list();
return boardList;
}
@Override
public Board select(int no) throws Exception {
Board board = boardMapper.select(no);
return board;
}
@Override
@Transactional
public int insert(Board board) throws Exception {
int result = boardMapper.insert(board); // μλ‘ μμ±λ λ°μ΄ν°μ pk κ°μ Έμ΄
int parentNo = boardMapper.maxPk();
board.setNo(parentNo);
result += uploadFiles(board);
return result;
}
@Override
public int update(Board board) throws Exception {
int result = boardMapper.update(board);
// νμΌ μ
λ‘λ
result += uploadFiles(board);
return result;
}
@Override
public int updateViews(int count, int no) throws Exception {
int result = boardMapper.updateViews(count, no);
return result;
}
public int uploadFiles(Board board) throws Exception {
String parentTable = "board";
int parentNo = board.getNo();
int result = 0;
List<MultipartFile> fileList = board.getFiles();
if( fileList != null && !fileList.isEmpty() ) {
Files fileInfo = new Files();
fileInfo.setParentTable(parentTable);
fileInfo.setParentNo(parentNo);
result = fileService.uploadFiles(fileInfo, fileList);
}
return result;
}
@Override
@Transactional
public int delete(int no) throws Exception {
int result = boardMapper.delete(no);
String parentTable = "board";
int parentNo = no;
// β
(New) - κ²μκΈμ μ’
μλ νμΌ μμ
if( result > 0 ) {
Files fileInfo = new Files();
fileInfo.setParentTable(parentTable);
fileInfo.setParentNo(parentNo);
int fileResult = fileService.deleteByParent(fileInfo);
result = fileResult;
}
return result;
}
}
Java
볡μ¬
μ ν νμΌ μμ
β’
FileService.java
β’
FileServiceImpl.java
β’
BoardServiceImpl.java
β’
FileService.java
package com.joeun.server.service;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import jakarta.servlet.http.HttpServletResponse;
public interface FileService {
// νμΌ λͺ©λ‘
public List<Files> list() throws Exception;
// νμΌ μ‘°ν
public Files select(int no) throws Exception;
// νμΌ λ±λ‘
public int insert(Files file) throws Exception;
// νμΌ μμ
public int update(Files file) throws Exception;
// νμΌ μμ
public int delete(int no) throws Exception;
// νμΌ μ
λ‘λ
public int uploadFiles(Files file, List<MultipartFile> fileList) throws Exception;
// νμΌ μ
λ‘λ
public int upload(Files file) throws Exception;
// νμΌ λͺ©λ‘ - λΆλͺ¨ κΈ°μ€
public List<Files> listByParent(Files file) throws Exception;
// νμΌ λ€μ΄λ‘λ
public int download(int no, HttpServletResponse response) throws Exception;
// νμΌ μμ - λΆλͺ¨ κΈ°μ€
public int deleteByParent(Files fileInfo) throws Exception;
// νμΌ μμ - noList κΈ°μ€
public int deleteByNoList(List<Integer> noList) throws Exception;
}
Java
볡μ¬
β’
FileServiceImpl.java
μΆκ°ν μ½λ
@Override
public int deleteByNoList(List<Integer> deleteFileNoList) throws Exception {
int result = 0;
if( deleteFileNoList != null && !deleteFileNoList.isEmpty() )
for (Integer deleteFileNo : deleteFileNoList) {
if( deleteFileNo == null ) continue;
fileMapper.delete(deleteFileNo);
log.info(deleteFileNo + "λ² νμΌ μμ ");
result++;
}
return result;
}
Java
볡μ¬
package com.joeun.server.service;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.FileMapper;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class FileServiceImpl implements FileService {
@Autowired
private FileMapper fileMapper;
@Value("${upload.path}") // application.properties μ μ€μ ν μ
λ‘λ κ²½λ‘ μμ±λͺ
private String uploadPath; // μ
λ‘λ κ²½λ‘
@Override
public List<Files> list() throws Exception {
List<Files> fileList = fileMapper.list();
return fileList;
}
@Override
public Files select(int no) throws Exception {
Files file = fileMapper.select(no);
return file;
}
@Override
public int insert(Files file) throws Exception {
int result = fileMapper.insert(file);
return result;
}
@Override
public int update(Files file) throws Exception {
int result = fileMapper.update(file);
return result;
}
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
@Override
public int uploadFiles(Files fileInfo, List<MultipartFile> fileList) throws Exception {
int result = 0;
for (MultipartFile file : fileList) {
result += uploadFile( fileInfo, file);
}
log.info(result + "κ° νμΌμ μ
λ‘λνμμ΅λλ€.");
return result;
}
@Override
public int deleteByNoList(List<Integer> deleteFileNoList) throws Exception {
int result = 0;
if( deleteFileNoList != null && !deleteFileNoList.isEmpty() )
for (Integer deleteFileNo : deleteFileNoList) {
if( deleteFileNo == null ) continue;
fileMapper.delete(deleteFileNo);
log.info(deleteFileNo + "λ² νμΌ μμ ");
result++;
}
return result;
}
@Override
@Transactional
public int upload(Files file) throws Exception {
int result = uploadFile(file, file.getFile());
if( result > 0 )
result = fileMapper.maxPk();
return result;
}
public int uploadFile(Files fileInfo, MultipartFile file) throws Exception {
int result = 0;
if( file.isEmpty() ) return result;
// νμΌ μ 보 : μλ³ΈνμΌλͺ
, νμΌ μ©λ, νμΌ λ°μ΄ν°
String originName = file.getOriginalFilename();
long fileSize = file.getSize();
byte[] fileData = file.getBytes();
// μ
λ‘λ κ²½λ‘
// νμΌλͺ
μ€λ³΅ λ°©μ§ λ°©λ²(μ μ±
)
// - λ μ§_νμΌλͺ
.νμ₯μ
// - UID_νμΌλͺ
.νμ₯μ
// UID_κ°μμ§.png
String fileName = UUID.randomUUID().toString() + "_" + originName;
// c:/upload/UID_κ°μμ§.png
String filePath = uploadPath + "/" + fileName;
// - μλ² μΈ‘, νμΌ μμ€ν
μ νμΌ λ³΅μ¬
File uploadFile = new File(uploadPath, fileName);
FileCopyUtils.copy(fileData, uploadFile); // νμΌ μ
λ‘λ
// - DB μ νμΌ μ 보 λ±λ‘
Files uploadedFile = new Files();
uploadedFile.setParentTable(fileInfo.getParentTable());
uploadedFile.setParentNo(fileInfo.getParentNo());
uploadedFile.setFileName(fileName);
uploadedFile.setFilePath(filePath);
uploadedFile.setOriginName(originName);
uploadedFile.setFileSize(fileSize);
uploadedFile.setFileCode(0);
result = fileMapper.insert(uploadedFile);
return result;
}
// νμΌ λͺ©λ‘ μ‘°ν
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int download(int fileNo, HttpServletResponse response) throws Exception {
// result
// 0 : νμΌ λ€μ΄λ‘λ μ²λ¦¬ μ€ν¨
// 1 : νμΌ λ€μ΄λ‘λ μ±κ³΅
Files file = fileMapper.select(fileNo);
if( file == null ) {
// BAD_REQUEST : 400, ν΄λΌμ΄μΈνΈμ μμ²μ΄ μλͺ»λμμμ μλ €μ£Όλ μνμ½λ
// response.setStatus(response.SC_BAD_REQUEST);
return 0;
}
String filePath = file.getFilePath(); // νμΌ κ²½λ‘
String fileName = file.getFileName(); // νμΌ μ΄λ¦
// λ€μ΄λ‘λ μλ΅μ μν ν€λ μΈν
// - ContentType : application/octet-stream
// - Content-Disposition : attachment, filename="νμΌλͺ
.νμ₯μ"
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
// νμΌ λ€μ΄λ‘λ
// - νμΌ μ
λ ₯
File downloadFile = new File(filePath);
FileInputStream fis = new FileInputStream(downloadFile);
// - νμΌ μΆλ ₯
ServletOutputStream sos = response.getOutputStream();
// λ€μ΄λ‘λ
FileCopyUtils.copy(fis, sos);
fis.close();
sos.close();
return 1;
}
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
@Override
public int deleteByNoList(List<Integer> deleteFileNoList) throws Exception {
int result = 0;
if( deleteFileNoList != null && !deleteFileNoList.isEmpty() )
for (Integer deleteFileNo : deleteFileNoList) {
if( deleteFileNo == null ) continue;
fileMapper.delete(deleteFileNo);
log.info(deleteFileNo + "λ² νμΌ μμ ");
result++;
}
return result;
}
}
Java
볡μ¬
β’
BoardServiceImpl.java
μΆκ°ν μ½λ
@Override
public int update(Board board) throws Exception {
int result = boardMapper.update(board);
// νμΌ μ
λ‘λ
result += uploadFiles(board);
// κ°λ³ νμΌ μμ
List<Integer> deleteFileNoList = board.getDeleteFileNoList();
result += fileService.deleteByNoList(deleteFileNoList);
return result;
}
Java
볡μ¬
package com.joeun.server.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Board;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.BoardMapper;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class BoardServiceImpl implements BoardService {
@Autowired
private BoardMapper boardMapper;
@Autowired
private FileService fileService;
@Override
public List<Board> list() throws Exception {
List<Board> boardList = boardMapper.list();
return boardList;
}
@Override
public Board select(int no) throws Exception {
Board board = boardMapper.select(no);
return board;
}
@Override
@Transactional
public int insert(Board board) throws Exception {
int result = boardMapper.insert(board); // μλ‘ μμ±λ λ°μ΄ν°μ pk κ°μ Έμ΄
int parentNo = boardMapper.maxPk();
board.setNo(parentNo);
result += uploadFiles(board);
return result;
}
@Override
public int update(Board board) throws Exception {
int result = boardMapper.update(board);
// νμΌ μ
λ‘λ
result += uploadFiles(board);
// β
(New) κ°λ³ νμΌ μμ
List<Integer> deleteFileNoList = board.getDeleteFileNoList();
result += fileService.deleteByNoList(deleteFileNoList);
return result;
}
@Override
public int updateViews(int count, int no) throws Exception {
int result = boardMapper.updateViews(count, no);
return result;
}
public int uploadFiles(Board board) throws Exception {
String parentTable = "board";
int parentNo = board.getNo();
int result = 0;
List<MultipartFile> fileList = board.getFiles();
if( fileList != null && !fileList.isEmpty() ) {
Files fileInfo = new Files();
fileInfo.setParentTable(parentTable);
fileInfo.setParentNo(parentNo);
result = fileService.uploadFiles(fileInfo, fileList);
}
return result;
}
@Override
@Transactional
public int delete(int no) throws Exception {
int result = boardMapper.delete(no);
String parentTable = "board";
int parentNo = no;
if( result > 0 ) {
Files fileInfo = new Files();
fileInfo.setParentTable(parentTable);
fileInfo.setParentNo(parentNo);
int fileResult = fileService.deleteByParent(fileInfo);
result = fileResult;
}
return result;
}
}
Java
볡μ¬
κ°λ³ νμΌ μμ
β’
FileService.java
β’
FileServiceImpl.java
β’
FileController.java
FileService.java
// νμΌ μμ
public int delete(int no) throws Exception;
Java
볡μ¬
package com.joeun.server.service;
import java.util.List;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import jakarta.servlet.http.HttpServletResponse;
public interface FileService {
// νμΌ λͺ©λ‘
public List<Files> list() throws Exception;
// νμΌ μ‘°ν
public Files select(int no) throws Exception;
// νμΌ λ±λ‘
public int insert(Files file) throws Exception;
// νμΌ μμ
public int update(Files file) throws Exception;
// νμΌ μμ
public int delete(int no) throws Exception;
// νμΌ μ
λ‘λ
public int uploadFiles(Files file, List<MultipartFile> fileList) throws Exception;
// νμΌ μ
λ‘λ
public int upload(Files file) throws Exception;
// νμΌ λͺ©λ‘ - λΆλͺ¨ κΈ°μ€
public List<Files> listByParent(Files file) throws Exception;
// νμΌ λ€μ΄λ‘λ
public int download(int no, HttpServletResponse response) throws Exception;
// νμΌ μμ - λΆλͺ¨ κΈ°μ€
public int deleteByParent(Files fileInfo) throws Exception;
// νμΌ μμ - noList κΈ°μ€
public int deleteByNoList(List<Integer> noList) throws Exception;
}
Java
볡μ¬
FileServiceImpl.java
@Override
public int delete(int no) throws Exception {
Files file = fileMapper.select(no);
if( file == null ) return 0;
String filePath = file.getFilePath();
File deleteFile = new File(filePath);
if( !deleteFile.exists() ) return 0;
boolean deleted = deleteFile.delete();
int result = 0;
if( deleted ) {
result = fileMapper.delete(no);
}
return result;
}
Java
볡μ¬
package com.joeun.server.service;
import java.io.File;
import java.io.FileInputStream;
import java.util.List;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import com.joeun.server.dto.Files;
import com.joeun.server.mapper.FileMapper;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class FileServiceImpl implements FileService {
@Autowired
private FileMapper fileMapper;
@Value("${upload.path}") // application.properties μ μ€μ ν μ
λ‘λ κ²½λ‘ μμ±λͺ
private String uploadPath; // μ
λ‘λ κ²½λ‘
@Override
public List<Files> list() throws Exception {
List<Files> fileList = fileMapper.list();
return fileList;
}
@Override
public Files select(int no) throws Exception {
Files file = fileMapper.select(no);
return file;
}
@Override
public int insert(Files file) throws Exception {
int result = fileMapper.insert(file);
return result;
}
@Override
public int update(Files file) throws Exception {
int result = fileMapper.update(file);
return result;
}
@Override
public int delete(int no) throws Exception {
Files file = fileMapper.select(no);
if( file == null ) return 0;
String filePath = file.getFilePath();
File deleteFile = new File(filePath);
if( !deleteFile.exists() ) return 0;
boolean deleted = deleteFile.delete();
int result = 0;
if( deleted ) {
result = fileMapper.delete(no);
}
return result;
}
@Override
public List<Files> listByParent(Files file) throws Exception {
List<Files> fileList = fileMapper.listByParent(file);
return fileList;
}
@Override
public int deleteByParent(Files fileInfo) throws Exception {
int result = 0;
List<Files> fileList = fileMapper.listByParent(fileInfo);
for (Files file : fileList) {
File deleteFile = new File(file.getFilePath());
if( !deleteFile.exists() ) continue;
if( !deleteFile.delete() ) continue;
int deleted = fileMapper.delete(file.getNo());
if( deleted > 0 ) result++;
}
log.info(result + "κ°μ νμΌμ μμ νμμ΅λλ€.");
return result;
}
@Override
public int download(int fileNo, HttpServletResponse response) throws Exception {
// result
// 0 : νμΌ λ€μ΄λ‘λ μ²λ¦¬ μ€ν¨
// 1 : νμΌ λ€μ΄λ‘λ μ±κ³΅
Files file = fileMapper.select(fileNo);
if( file == null ) {
// BAD_REQUEST : 400, ν΄λΌμ΄μΈνΈμ μμ²μ΄ μλͺ»λμμμ μλ €μ£Όλ μνμ½λ
// response.setStatus(response.SC_BAD_REQUEST);
return 0;
}
String filePath = file.getFilePath(); // νμΌ κ²½λ‘
String fileName = file.getFileName(); // νμΌ μ΄λ¦
// λ€μ΄λ‘λ μλ΅μ μν ν€λ μΈν
// - ContentType : application/octet-stream
// - Content-Disposition : attachment, filename="νμΌλͺ
.νμ₯μ"
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
// νμΌ λ€μ΄λ‘λ
// - νμΌ μ
λ ₯
File downloadFile = new File(filePath);
FileInputStream fis = new FileInputStream(downloadFile);
// - νμΌ μΆλ ₯
ServletOutputStream sos = response.getOutputStream();
// λ€μ΄λ‘λ
FileCopyUtils.copy(fis, sos);
// byte[] buffer = new byte[1024]; // 1024bytes = 1KB λ¨μ λ²νΌ
// int data;
// while( (data = fis.read(buffer)) != -1 ) { // 1KB μ© νμΌμ
λ ₯
// sos.write(buffer, 0, data); // 1KB μ© νμΌμΆλ ₯
// }
fis.close();
sos.close();
return 1;
}
@Override
public int uploadFiles(Files fileInfo, List<MultipartFile> fileList) throws Exception {
int result = 0;
for (MultipartFile file : fileList) {
result += uploadFile( fileInfo, file);
}
log.info(result + "κ° νμΌμ μ
λ‘λνμμ΅λλ€.");
return result;
}
@Override
public int deleteByNoList(List<Integer> deleteFileNoList) throws Exception {
int result = 0;
if( deleteFileNoList != null && !deleteFileNoList.isEmpty() )
for (Integer deleteFileNo : deleteFileNoList) {
if( deleteFileNo == null ) continue;
fileMapper.delete(deleteFileNo);
log.info(deleteFileNo + "λ² νμΌ μμ ");
result++;
}
return result;
}
@Override
@Transactional
public int upload(Files file) throws Exception {
int result = uploadFile(file, file.getFile());
if( result > 0 )
result = fileMapper.maxPk();
return result;
}
public int uploadFile(Files fileInfo, MultipartFile file) throws Exception {
int result = 0;
if( file.isEmpty() ) return result;
// νμΌ μ 보 : μλ³ΈνμΌλͺ
, νμΌ μ©λ, νμΌ λ°μ΄ν°
String originName = file.getOriginalFilename();
long fileSize = file.getSize();
byte[] fileData = file.getBytes();
// μ
λ‘λ κ²½λ‘
// νμΌλͺ
μ€λ³΅ λ°©μ§ λ°©λ²(μ μ±
)
// - λ μ§_νμΌλͺ
.νμ₯μ
// - UID_νμΌλͺ
.νμ₯μ
// UID_κ°μμ§.png
String fileName = UUID.randomUUID().toString() + "_" + originName;
// c:/upload/UID_κ°μμ§.png
String filePath = uploadPath + "/" + fileName;
// - μλ² μΈ‘, νμΌ μμ€ν
μ νμΌ λ³΅μ¬
File uploadFile = new File(uploadPath, fileName);
FileCopyUtils.copy(fileData, uploadFile); // νμΌ μ
λ‘λ
// - DB μ νμΌ μ 보 λ±λ‘
Files uploadedFile = new Files();
uploadedFile.setParentTable(fileInfo.getParentTable());
uploadedFile.setParentNo(fileInfo.getParentNo());
uploadedFile.setFileName(fileName);
uploadedFile.setFilePath(filePath);
uploadedFile.setOriginName(originName);
uploadedFile.setFileSize(fileSize);
uploadedFile.setFileCode(0);
result = fileMapper.insert(uploadedFile);
return result;
}
}
Java
볡μ¬
FileController.java
package com.joeun.server.controller;
import java.io.File;
import java.io.FileInputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.joeun.server.dto.Files;
import com.joeun.server.service.FileService;
import com.joeun.server.utils.MediaUtil;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
@RequestMapping("/file")
public class FileController {
@Autowired
private FileService fileService;
@Autowired
private ResourceLoader resourceLoader;
/**
* νμΌ λ€μ΄λ‘λ
* @param fileNo
* @param response
* @throws Exception
*/
@GetMapping("/{no}")
public void fileDownload(@PathVariable("no") int no
,HttpServletResponse response) throws Exception {
// νμΌ μ‘°ν
Files file = fileService.select(no);
// νμΌμ΄ μ‘΄μ¬νμ§ μμΌλ©΄,
if( file == null ) {
// μλ΅ μνμ½λ : 400, ν΄λΌμ΄μΈνΈμ μμ²μ΄ μλͺ»λμμμ λνλ΄λ μνμ½λ
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
}
String fileName = file.getFileName(); // νμΌ λͺ
String filePath = file.getFilePath(); // νμΌ κ²½λ‘
// νμΌ λ€μ΄λ‘λλ₯Ό μν ν€λ μΈν
// - ContentType : application/octet-straem
// - Content-Disposition : attachment; fileanme="νμΌλͺ
.νμ₯μ"
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
// νμΌ μ
λ ₯
File downloadFile = new File(filePath);
FileInputStream fis = new FileInputStream(downloadFile);
ServletOutputStream sos = response.getOutputStream();
// λ€μ΄λ‘λ
FileCopyUtils.copy(fis, sos);
}
/**
* μ΄λ―Έμ§ μΈλ€μΌ
* @param no
* @param response
* @throws Exception
*/
@GetMapping("/img/{no}")
public void showImg(@PathVariable Integer no, HttpServletResponse response) throws Exception {
Files file = fileService.select(no);
String filePath = (file != null) ? file.getFilePath() : null;
Resource resource = resourceLoader.getResource("classpath:static/img/no-image.png");
File imgFile;
if (filePath == null || !(imgFile = new File(filePath)).exists()) {
// νμΌμ΄ μ‘΄μ¬νμ§ μκ±°λ νμΌ κ²½λ‘κ° nullμΈ κ²½μ°
imgFile = resource.getFile();
}
String ext = filePath.substring(filePath.lastIndexOf(".") + 1);
MediaType mType = MediaUtil.getMediaType(ext);
if (mType == null) {
// μ΄λ―Έμ§ νμ
μ΄ μλ κ²½μ°
response.setContentType(MediaType.IMAGE_PNG_VALUE); // κΈ°λ³Έμ μΌλ‘ PNGλ‘ μ€μ
imgFile = resource.getFile();
} else {
// μ΄λ―Έμ§ νμ
μΌ κ²½μ°
response.setContentType(mType.toString());
}
FileInputStream fis = new FileInputStream(imgFile);
ServletOutputStream sos = response.getOutputStream();
FileCopyUtils.copy(fis, sos);
}
/**
* νμΌ μμ
* @param file
* @return
* @throws Exception
*/
@DeleteMapping("/{no}")
public ResponseEntity<String> deleteFile(@PathVariable Integer no) throws Exception {
log.info("[DELETE] - /file");
int fileNo = no;
log.info("fileNo : " + fileNo);
if( fileNo == 0 )
return new ResponseEntity<String>("FAIL", HttpStatus.BAD_REQUEST);
int result = fileService.delete(fileNo);
if( result == 0 )
return new ResponseEntity<String>("FAIL", HttpStatus.OK);
return new ResponseEntity<String>("SUCCESS", HttpStatus.OK);
}
}
Java
볡μ¬
React (Front-End)
React λ‘ νμΌ μ
λ‘λ, μ‘°ν, μμ UI λ° API λ₯Ό ꡬνν©λλ€.
νμΌ μ λ‘λ
νμΌ λ±λ‘ UI μΆκ°
BoardInsertForm.jsx
import React, { useState } from 'react'
import { Link } from 'react-router-dom'
import './BoardInsertForm.css'
const BoardInsertForm = ({ onInsert }) => {
// state μ€μ
const [title, setTitle] = useState('');
const [writer, setWriter] = useState('');
const [content, setContent] = useState('');
const [files, setFiles] = useState(null); // β
files state μΆκ°
const handleChangeTitle = (e) => {
setTitle(e.target.value)
}
const handleChangeWriter = (e) => {
setWriter(e.target.value)
}
const handleChangeContent = (e) => {
setContent(e.target.value)
}
// β
νμΌ νΈλ€λ¬ μΆκ°
const handleFileChange = (e) => {
setFiles(e.target.files);
};
const onSubmit = () => {
const formData = new FormData();
formData.append('title', title);
formData.append('writer', writer);
formData.append('content', content);
const headers = {
headers: {
'Content-Type' : 'multipart/form-data',
},
};
if (files) {
for (let i = 0; i < files.length; i++) {
formData.append(`files[${i}]`, files[i]);
}
}
// onInsert(title, writer, content)
// onInsert({title,writer,content,files}, headers) // formData μ¬μ© β
onInsert(formData, headers) // formData μ¬μ© β
}
return (
<div className='container'>
<h1 className='title'>κ²μκΈ λ±λ‘</h1>
<table className='table'>
<tbody>
<tr>
<td>μ λͺ©</td>
<td>
<input type="text"
className='form-input'
value={title}
onChange={handleChangeTitle} />
</td>
</tr>
<tr>
<td>μμ±μ</td>
<td>
<input type="text"
className='form-input'
value={writer}
onChange={handleChangeWriter} />
</td>
</tr>
<tr>
<td colSpan={2}>λ΄μ©</td>
</tr>
<tr>
<td colSpan={2}>
<textarea cols="40" rows="10"
className='form-input'
value={content}
onChange={handleChangeContent}
></textarea>
</td>
</tr>
<tr>
<td>νμΌ</td>
<td>
<input type='file' onChange={handleFileChange} multiple />
</td>
</tr>
</tbody>
</table>
<div className='btn-box'>
<Link to="/boards" className='btn'>λͺ©λ‘</Link>
<button onClick={ onSubmit } className='btn'>λ±λ‘</button>
</div>
</div>
)
}
export default BoardInsertForm
JavaScript
볡μ¬
νμΌ μ λ‘λ μμ² API
files.js
import axios from 'axios';
// μ
λ‘λ
export const upload = (formData, headers) => axios.post(`/file/upload`, formData, headers)
JavaScript
볡μ¬
οΈ νμΌ μ‘°ν
νμΌ λͺ©λ‘ μ‘°ν UI λ° API μΆκ°
BoardReadContainer.jsx
import React, { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import * as boards from '../apis/boards';
import BoardRead from '../components/BoardRead/BoardRead';
// π©βπ» κ²μκΈ μ‘°ν
const BoardReadContainer = () => {
const { no } = useParams()
const [board, setBoard] = useState({});
const [fileList, setFileList] = useState([]);
const [isLoading, setLoading] = useState(false);
const getBoard = async () => {
setLoading(true)
try {
const response = await boards.select(no);
const data = response.data;
console.log(data);
const board = data.board;
const fileList = data.fileList;
setBoard(board);
setFileList(fileList);
}
catch(e) {
console.log(e);
}
setLoading(false)
}
useEffect( () => {
getBoard()
},[])
return (<BoardRead no={no}
board={board}
fileList={fileList}
isLoading={isLoading}
/>)
}
export default BoardReadContainer
JavaScript
볡μ¬
BoardRead.jsx
import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';
import * as format from '../../apis/format';
import './BoardRead.css';
const BoardRead = ({ no, board, fileList, isLoading }) => {
return (
<div className='container'>
<h1 className='title'>κ²μκΈ μ‘°ν</h1>
<h3>λ²νΈ : {no}</h3>
<hr/>
{ isLoading &&
<div>
<img src="/img/loading.webp" alt="loading" />
</div>
}
{ !isLoading && board && (
<table border={1} className='table'>
<tbody>
<tr>
<td>λ²νΈ</td>
<td>
<input type="text" className='form-input' value={board.no} readOnly />
</td>
</tr>
<tr>
<td>λ±λ‘μΌμ</td>
<td>
<input type="text" className='form-input' value={format.formatDate( board.regDate )} readOnly />
</td>
</tr>
<tr>
<td>μ λͺ©</td>
<td>
<input type="text" className='form-input' value={board.title} readOnly />
</td>
</tr>
<tr>
<td>μμ±μ</td>
<td>
<input type="text" className='form-input' value={board.writer} readOnly />
</td>
</tr>
<tr>
<td colSpan={2}>λ΄μ©</td>
</tr>
<tr>
<td colSpan={2}>
<textarea cols="40" rows="10"
className='form-input'
value={board.content}
readOnly></textarea>
</td>
</tr>
<tr>
<td colSpan={2}>νμΌ</td>
</tr>
<tr>
<td colSpan={2}>
{ fileList.map( (file) => (
<div className='file-box' key={file.no}>
<div className="item">
<span>{file.originName}({ format.byteToUnit(file.fileSize) })</span>
</div>
<div className="item">
</div>
</div>
))}
</td>
</tr>
</tbody>
</table>
)}
<hr />
<div className="btn-box">
<Link className='btn' to="/boards">λͺ©λ‘</Link>
<Link className='btn' to={`/boards/update/${no}`}>μμ </Link>
</div>
</div>
)
}
export default BoardRead
JavaScript
볡μ¬
λ€μ΄λ‘λ UI λ° API μΆκ°
BoardRead.jsx
<button className="btn" onClick={() => handleDownload(file.no, file.originName)}>λ€μ΄λ‘λ</button>
JavaScript
볡μ¬
import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';
import * as format from '../../apis/format';
import './BoardRead.css';
const BoardRead = ({ no, board, fileList, isLoading }) => {
return (
<div className='container'>
<h1 className='title'>κ²μκΈ μ‘°ν</h1>
<h3>λ²νΈ : {no}</h3>
<hr/>
{ isLoading &&
<div>
<img src="/img/loading.webp" alt="loading" />
</div>
}
{ !isLoading && board && (
<table border={1} className='table'>
<tbody>
<tr>
<td>λ²νΈ</td>
<td>
<input type="text" className='form-input' value={board.no} readOnly />
</td>
</tr>
<tr>
<td>λ±λ‘μΌμ</td>
<td>
<input type="text" className='form-input' value={format.formatDate( board.regDate )} readOnly />
</td>
</tr>
<tr>
<td>μ λͺ©</td>
<td>
<input type="text" className='form-input' value={board.title} readOnly />
</td>
</tr>
<tr>
<td>μμ±μ</td>
<td>
<input type="text" className='form-input' value={board.writer} readOnly />
</td>
</tr>
<tr>
<td colSpan={2}>λ΄μ©</td>
</tr>
<tr>
<td colSpan={2}>
<textarea cols="40" rows="10"
className='form-input'
value={board.content}
readOnly></textarea>
</td>
</tr>
<tr>
<td colSpan={2}>νμΌ</td>
</tr>
<tr>
<td colSpan={2}>
{ fileList.map( (file) => (
<div className='file-box' key={file.no}>
<div className="item">
<span>{file.originName}({ format.byteToUnit(file.fileSize) })</span>
</div>
<div className="item">
<button className="btn" onClick={() => handleDownload(file.no, file.originName)}>λ€μ΄λ‘λ</button>
</div>
</div>
))}
</td>
</tr>
</tbody>
</table>
)}
<hr />
<div className="btn-box">
<Link className='btn' to="/boards">λͺ©λ‘</Link>
<Link className='btn' to={`/boards/update/${no}`}>μμ </Link>
</div>
</div>
)
}
export default BoardRead
JavaScript
볡μ¬
files.js
import axios from 'axios';
// μ
λ‘λ
export const upload = (formData, headers) => axios.post(`/file/upload`, formData, headers)
// λ€μ΄λ‘λ
export const download = (fileNo) => axios.get(`/file/${fileNo}`, {responseType: 'blob',} )
JavaScript
볡μ¬
μΈλ€μΌ μ΄λ―Έμ§ UI μΆκ°
BoardRead.jsx
<img src={`/file/img/${file.no}`} alt={file.fileName} />
JavaScript
볡μ¬
import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';
import * as format from '../../apis/format';
import './BoardRead.css';
const BoardRead = ({ no, board, fileList, isLoading }) => {
return (
<div className='container'>
<h1 className='title'>κ²μκΈ μ‘°ν</h1>
<h3>λ²νΈ : {no}</h3>
<hr/>
{ isLoading &&
<div>
<img src="/img/loading.webp" alt="loading" />
</div>
}
{ !isLoading && board && (
<table border={1} className='table'>
<tbody>
<tr>
<td>λ²νΈ</td>
<td>
<input type="text" className='form-input' value={board.no} readOnly />
</td>
</tr>
<tr>
<td>λ±λ‘μΌμ</td>
<td>
<input type="text" className='form-input' value={format.formatDate( board.regDate )} readOnly />
</td>
</tr>
<tr>
<td>μ λͺ©</td>
<td>
<input type="text" className='form-input' value={board.title} readOnly />
</td>
</tr>
<tr>
<td>μμ±μ</td>
<td>
<input type="text" className='form-input' value={board.writer} readOnly />
</td>
</tr>
<tr>
<td colSpan={2}>λ΄μ©</td>
</tr>
<tr>
<td colSpan={2}>
<textarea cols="40" rows="10"
className='form-input'
value={board.content}
readOnly></textarea>
</td>
</tr>
<tr>
<td colSpan={2}>νμΌ</td>
</tr>
<tr>
<td colSpan={2}>
{ fileList.map( (file) => (
<div className='file-box' key={file.no}>
<div className="item">
<img src={`/file/img/${file.no}`} alt={file.fileName} />
<span>{file.originName}({ format.byteToUnit(file.fileSize) })</span>
</div>
<div className="item">
<button className="btn" onClick={() => handleDownload(file.no, file.originName)}>λ€μ΄λ‘λ</button>
</div>
</div>
))}
</td>
</tr>
</tbody>
</table>
)}
<hr />
<div className="btn-box">
<Link className='btn' to="/boards">λͺ©λ‘</Link>
<Link className='btn' to={`/boards/update/${no}`}>μμ </Link>
</div>
</div>
)
}
export default BoardRead
JavaScript
볡μ¬
νμΌ μμ
μμ ν νμΌ μ²΄ν¬λ°μ€ UI μΆκ°, νμΌ μμ λ²νΌ UI λ° API μΆκ°
import React, { useEffect, useState } from 'react'
import { Link } from 'react-router-dom'
import * as format from '../../apis/format'
const BoardUpdateForm = ({ no, board, fileList, onUpdate, onDelete, isLoading, onDownload, onDeleteFile }) => {
// state μ€μ
const [title, setTitle] = useState('')
const [writer, setWriter] = useState('')
const [content, setContent] = useState('')
const [files, setFiles] = useState(null); // β
files state μΆκ°
const [fileNoList, setFileList] = useState([]) // β
νμΌ μ ν μμ - deleteFileNoList
const handleChangeTitle = (e) => {
setTitle(e.target.value)
}
const handleChangeWriter = (e) => {
setWriter(e.target.value)
}
const handleChangeContent = (e) => {
setContent(e.target.value)
}
const onSubmit = () => {
const formData = new FormData();
formData.append('no', no);
formData.append('title', title);
formData.append('writer', writer);
formData.append('content', content);
console.log(`fileNoList --------------------------------------`);
console.log(fileNoList);
formData.append('deleteFileNoList', fileNoList);
const headers = {
headers: {
'Content-Type' : 'multipart/form-data',
},
};
if (files) {
for (let i = 0; i < files.length; i++) {
formData.append(`files[${i}]`, files[i]);
}
}
// onUpdate(no, title, writer, content);
// onUpdate({no, title, writer, content}, headers);
onUpdate(formData, headers);
}
const handleDelete = () => {
const check = window.confirm('μ λ§λ‘ μμ νμκ² μ΅λκΉ?')
if( check )
onDelete(no)
}
const handleDownload = (fileNo, fileName) => {
onDownload(fileNo, fileName)
}
const handleDeleteFile =(fileNo) => {
const check = window.confirm('μ λ§λ‘ μμ νμκ² μ΅λκΉ?')
if( check )
onDeleteFile(fileNo)
}
// β
νμΌ νΈλ€λ¬ μΆκ°
const handleFileChange = (e) => {
setFiles(e.target.files);
};
// νμΌ λ²νΈ 체ν¬
const checkFileNo = (no) => {
setFileList( [...fileNoList, no] )
}
useEffect( () => {
if( board ) {
setTitle(board.title);
setWriter(board.writer)
setContent(board.content)
}
}, [board])
return (
<div className='container'>
<h1 className='title'>κ²μκΈ μμ </h1>
<h3>λ²νΈ : {no}</h3>
<hr/>
{ isLoading &&
<div>
<img src="/img/loading.webp" alt="loading" />
</div>
}
{ !isLoading && board && (
<table border={1} className='table'>
<tbody>
<tr>
<td>λ²νΈ</td>
<td>
<input type="text" className='form-input' value={board.no} readOnly />
</td>
</tr>
<tr>
<td>λ±λ‘μΌμ</td>
<td>
<input type="text" className='form-input' value={ format.formatDate(board.regDate) } readOnly />
</td>
</tr>
<tr>
<td>μ λͺ©</td>
<td>
<input type="text" className='form-input' value={title} onChange={handleChangeTitle} />
</td>
</tr>
<tr>
<td>μμ±μ</td>
<td>
<input type="text" className='form-input' value={writer} onChange={handleChangeWriter} />
</td>
</tr>
<tr>
<td colSpan={2}>λ΄μ©</td>
</tr>
<tr>
<td colSpan={2}>
<textarea cols="40" rows="10"
className='form-input'
value={content}
onChange={handleChangeContent}></textarea>
</td>
</tr>
<tr>
<td>νμΌ μ
λ‘λ</td>
<td>
<input type='file' onChange={handleFileChange} multiple />
</td>
</tr>
{ fileList && fileList.length > 0 &&
<tr>
<td>μμ </td>
<td>νμΌ</td>
</tr>
}
{ fileList.length == 0 &&
<tr>
<td colSpan={2} align='center'>
μ
λ‘λλ νμΌμ΄ μμ΅λλ€.
</td>
</tr>
}
{ fileList.map( (file) => (
<tr>
<td>
<input type="checkbox" onChange={ () => checkFileNo(file.no) } />
</td>
<td>
<div className='file-box' key={file.no}>
<div className="item">
<img src={`/file/img/${file.no}`} alt={file.fileName} />
<span>{file.originName}({ format.byteToUnit(file.fileSize) })</span>
</div>
<div className="item">
<button className="btn" onClick={() => handleDownload(file.no, file.originName)}>λ€μ΄λ‘λ</button>
<button className="btn" onClick={() => handleDeleteFile(file.no)}>μμ </button>
</div>
</div>
</td>
</tr>
))}
</tbody>
</table>
)}
<hr />
<div className="btn-box">
<div className="item">
<Link to="/boards" className='btn'>λͺ©λ‘</Link>
</div>
<div className="item">
<button className='btn' onClick={ handleDelete }>μμ </button>
<button className='btn' tton onClick={ onSubmit }>μμ </button>
</div>
</div>
</div>
)
}
export default BoardUpdateForm
JavaScript
볡μ¬