이전편
https://tinylittlelife.tistory.com/290
이번엔 Springboot 에서 파일 객체들을 어떻게 받을 지 봅시다.
appication.properties
# TODO : file upload size
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
우리가 multipart 객체로 파일들을 받을건데 그 size 를 지정해줄 수 있습니다.
일단 Entity 부분부터 보면 @Lob byte[] 타입으로 되어있는데 이는
Oracle SQL 기준 BLOB 타입을 의미합니다.
또한, MySQL 에서는 저는 longblob 타입을 사용합니다.
# ProjectsImages
@Entity
@Getter
@Table(name = "PROJECTS_IMAGES")
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Setter
@DynamicInsert
@DynamicUpdate
// soft delete
@Where(clause = "DELETE_YN = 'N'")
@SQLDelete(sql = "UPDATE PROJECTS_IMAGES SET DELETE_YN = 'Y', DELETE_TIME=NOW() WHERE PID = ?")
public class ProjectImages extends BaseTimeEntity {
@Id
private String uuid;
private String fileName;
@Lob
private byte[] projectsImgData; // 실제 데이터 부분
private String projectsImgUrl;
private Integer pid;
}
이번에는 다들 궁금해하실 Controller 부분입니다.
Projects 객체는 무시해주세요.. ㅎ..
@RestController
@Slf4j
@RequestMapping("/api")
public class ProjectsController {
@Autowired
ProjectsService projectsService;
/**
* Todo : 업로드
*
* @param description
* @param frontName
* @param backendName
* @param dbmsName
* @param publishName
* @param webUrl
* @param currentFiles
* @return
*/
@PostMapping("/projects/upload")
public ResponseEntity<Object> create( // 객체로 받을수 없어서 각각 변수로 받아와야 함
@RequestParam(defaultValue = "") String description, // 제목
@RequestParam(defaultValue = "") String frontName, // 제목
@RequestParam(defaultValue = "") String backendName, // 제목
@RequestParam(defaultValue = "") String dbmsName, // 제목
@RequestParam(defaultValue = "") String publishName, // 제목
@RequestParam(defaultValue = "") String webUrl, // 제목
@RequestParam("currentFiles") List<MultipartFile> currentFiles
) {
try {
System.out.println(webUrl);
Projects projects = new Projects(null, description, frontName, backendName, dbmsName, publishName, webUrl);
projectsService.save(
null, // 기본키
projects, // 음...객체군
currentFiles // 첨부파일
); // db 저장
return new ResponseEntity<>("업로드 성공", HttpStatus.OK);
} catch (Exception e) {
// DB 에러가 났을경우 : INTERNAL_SERVER_ERROR 프론트엔드로 전송
log.info(e.getMessage());
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
저는 이렇게 했습니다..만 다른 방식들도 가능합니다.
위를 보시면 @RequestParam 으로 List<MultipartFile> 로 파일 여러개를 받을 수 있습니다.
이번에는 Service 부분입니다.
# ProjectsService
@Service
@Slf4j
public class ProjectsService {
@Autowired
ProjectsRepository projectsRepository;
@Autowired
ProjectImagesService projectImagesService;
public Projects save(String uuid, Projects proejcts, List<MultipartFile> files) {
Projects projects1 = projectsRepository.save(proejcts);
for (MultipartFile file : files) {
projectImagesService.save(uuid, projects1.getPid(), file);
}
return projects1;
}
}
# ProjectsImagesService
@Service
@Slf4j
public class ProjectImagesService {
@Autowired
ProjectImagesRepository projectImagesRepository;
// todo : 저장(수정) 함수(업로드)
public ProjectImages save(String uuid,
int pid,
MultipartFile file // 첨부파일 객체 (MultipartFile)
) {
ProjectImages projectImages2 = null;
try {
// 기본키 : uuid
if (uuid == null) {
// 저장 실행
// 1) DB에 이미지 저장
// 2) DB에 이미지를 다운로드 할 수 있는 url 저장 (다운로드 URL 만들기 필요)
// 3) 파일명(중복이 안되는) : uuid(기본키) 사용(유일값)
// TODO : 1) uuid 만들기
String tmpUuid = UUID.randomUUID() // UUID 랜덤 생성함수
.toString() // 문자열 변환
.replace("-", ""); // -를 빈문자열로 변환(편의상)
// TODO : 2) 다운로드 url 만들기
String fileDownloadUri = ServletUriComponentsBuilder
.fromCurrentContextPath() // 기본 경로 : localhost:8000
.path("/api/project-images/") // 추가 경로 : 기본경로 + "/api/skill-file/"
.path(tmpUuid) // 기본경로 + 추가경로 + uuid 붙임
.toUriString(); // 문자열 변환
// 최종 url 예 : localhost:8000/api/advanced/projectImages/xxxxiiiii
// TODO : 3) 위의 정보를 ProjectImages 객체에 저장 후 DB save 함수 실행
ProjectImages projectImages = new ProjectImages(
tmpUuid, // UUID
file.getOriginalFilename(), // 실제 이미지 파일명 (예)course.jpg)
file.getBytes(), // 이미지 파일 크기 (100byte...)
fileDownloadUri
, pid); // 다운로드 url
projectImages2 = projectImagesRepository.save(projectImages);
} else {
// 수정 실행
// TODO : 2) 다운로드 url 만들기
String fileDownloadUri = ServletUriComponentsBuilder
.fromCurrentContextPath() // 기본 경로 : localhost:8000
.path("/api/project-images/") // 추가 경로 : 기본경로 + /api/advanced/projectImages/
.path(uuid) // 기본경로 + 추가경로 + 기존 uuid 붙임
.toUriString(); // 문자열 변환
// 최종 url 예 : localhost:8000/api/advanced/projectImages/xxxxiiiii
// TODO : 3) 위의 정보를 ProjectImages 객체에 저장 후 DB save 함수 실행
ProjectImages projectImages = new ProjectImages(
uuid, // 기존 UUID
file.getOriginalFilename(), // 실제 이미지 파일명 (예)course.jpg)
file.getBytes(), // 이미지 파일 크기 (100byte...)
fileDownloadUri,pid); // 다운로드 url
projectImages2 = projectImagesRepository.save(projectImages);
}
} catch (Exception e) {
log.debug(e.getMessage());
}
return projectImages2;
}
}
저는 이런식으로 했지만 여러분은 수정해서 ㅎㅎ..
유심히 봐야할 부분은 save 부분이네요
uuid 란?
범용 고유 식별자(Universally Unique Identifier, UUID) 는 해당 타입의 다른 모든 리소스 중에서 리소스를 고유하게 식별하는 데 사용되는 레이블입니다. 컴퓨터 시스템은 매우 큰 난수를 사용해 로컬에서 UUID를 생성합니다.
라고는 하는데 그냥 primary key로 String 형식이다 라고 합시다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
1)
uuid 가 null 일 경우 save , uuid 가 있을 경우 update 하는 구문입니다.
따라서 save인 경우 uuid 를 생성합니다.
2)
나중에 보실 다운로드 url을 만드는 과정입니다.
이것을 활용하여
<img src="url"/> 로 다운로드 가능한 형식으로 만듭니다.
두 과정을 거쳤다면 끝입니다 save 해줍시다.
여러장이 잘 들어왔군요
그래서 img_url 이 있으면 파일을 어떻게 보내요?라는 질문은 이쪽입니다.
# ProjectImagesController
@RestController
@Slf4j
@RequestMapping("/api")
public class ProjectImagesController {
@Autowired
ProjectImagesService projectImagesService;
// 다운로드 URL에 따라 자동으로 첨부파일 다운로드 받게 해주는 함수(자동 실행)
// 예) <img src="url"/ > => 이미지 자동 다운로드해서 화면에 이미지 표시됨
// http://localhost:8000/api/projectImages/{uuid} (현재 함수 url === 다운로드 url)
@GetMapping("/project-images/{uuid}")
public ResponseEntity<byte[]> findByIdDownloading(@PathVariable String uuid) {
try {
ProjectImages projectImages = projectImagesService.findById(uuid).get(); // 상세조회
return ResponseEntity.ok()
// Todo : header() : 헤더 (1)첨부파일로 전송한다고 표시, (2) 첨부파일명 표시
// HttpHeaders.CONTENT_DISPOSITION : 첨부파일 표시
// "attachment; filename=\"" + projectImages.getFileName() + "\"" : 첨부파일명 표시
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + projectImages.getFileName() + "\"")
// TODO : body() : 바디 - 실제 이미지 전송(리액트)
.body(projectImages.getProjectsImgData()); // 첨부파일
} catch (Exception e) {
log.info(e.getMessage());
return ResponseEntity.internalServerError().build();
}
}
}
# ProjectImagesService
// Todo : 이미지 상세 조회
public ProjectImagesDto selectByIdProjectImages (String uuid) {
return projectImagesRepository.selectByIdProjectImages(uuid);
}
위를 꺼내보면
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + projectImages.getFileName()+"\"")
.body(projectImages.getProjectsImgData()); // 첨부파일
이런식이네요
끝
'SpringBoot' 카테고리의 다른 글
Springboot 2.x 버젼 - QueryDSL 설정 (0) | 2023.12.23 |
---|---|
React , Springboot - 파일 한장 올리기 (0) | 2023.12.21 |
SprinBoot - logback , log4jdbc 설정 (1) | 2023.12.17 |
Sprinboot 3.x버젼 - QueryDSL 설정과 간단하게 사용해보자 (1) | 2023.12.17 |
Springboot - Security (1) | 2023.12.14 |