블로그 글을 작성하면 파일을 업로드할 수 있는 기능이 있다. 오늘은 스프링부트로 파일 업로드 기능을 구현하려고 한다. 파일 업로드만 하는 기능을 구현하고, 다운로드 기능은 추후에 추가를 하려고 한다.
개발 구성
IDE : IntelliJ
JDK(자바) : 17
STS(스프링부트 버전) : 3.2.1
Language : Java
플러그인
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'org.postgresql:postgresql'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
프로젝트 구조
application.yaml
spring:
datasource:
hikari:
maximum-pool-size: 4
username: testuser
password: testpass
url: jdbc:postgresql://localhost:5432/study
# JPA
jpa:
hibernate:
ddl-auto: update
properties:
hibernate:
format_sql: true
show-sql: true
servlet:
multipart:
location: upload-dir
enabled: true
file:
dir: /Users/ihseo/upload-dir/
- 하단에 있는 file 경로를 설정해야지 원하는 폴더에 파일을 업로드할 수 있다.
UploadFile.java
package com.study.file_upload.entity;
import jakarta.persistence.*;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.ColumnDefault;
import org.hibernate.annotations.DynamicInsert;
import org.springframework.data.annotation.CreatedDate;
import java.time.LocalDateTime;
@Entity
@Getter
@DynamicInsert
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class UploadFile {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", updatable = false, unique = true)
private long id;
@Column(name = "original_name", nullable = false)
private String originalName;
@Column(name = "save_name", nullable = false)
private String saveName;
@Column(name = "size", nullable = false)
private long size;
@Column(name = "delete_yn")
private String deleteYn;
@CreatedDate
@Column(name = "created_at")
private LocalDateTime createdAt;
@Builder
public UploadFile(String originalName, String saveName, long size) {
this.originalName = originalName;
this.saveName = saveName;
this.size = size;
}
}
FileUploadDto.java
package com.study.file_upload.api.dto;
import com.study.file_upload.entity.UploadFile;
import lombok.Builder;
import lombok.Getter;
@Getter
public class FileUploadDto {
private Long id; // 파일 번호 (PK)
private final String originalName; // 원본 파일명
private final String saveName; // 저장 파일명
private final long size; // 파일 크기
@Builder
public FileUploadDto(String originalName, String saveName, long size) {
this.originalName = originalName;
this.saveName = saveName;
this.size = size;
}
public UploadFile toEntity() {
return UploadFile.builder()
.originalName(originalName)
.saveName(saveName)
.size(size)
.build();
}
}
UploadFileRepository.java
package com.study.file_upload.api.repository;
import com.study.file_upload.entity.UploadFile;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UploadFileRepository extends JpaRepository<UploadFile, Long> {
}
FileService.java
package com.study.file_upload.api.service;
import com.study.file_upload.api.dto.FileUploadDto;
import com.study.file_upload.api.repository.UploadFileRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
@Slf4j
@Service
@RequiredArgsConstructor
public class FileService {
@Value("${file.dir}")
private String filePath;
private final UploadFileRepository uploadFileRepository;
@Transactional
public void save(MultipartFile file) {
FileUploadDto fileDto = saveFile(file);
if (fileDto != null) {
uploadFileRepository.save(fileDto.toEntity());
}
}
// 파일 업로드
private FileUploadDto saveFile(MultipartFile file) {
FileUploadDto dto = null;
if (file != null) {
String originalName = file.getOriginalFilename();
String saveName = UUID.randomUUID() + "_" + originalName;
long size = file.getSize();
try {
// 파일 업로드
log.info("file path : {}", filePath);
File localFile = new File(filePath + "/" + saveName);
file.transferTo(localFile);
dto = FileUploadDto.builder()
.originalName(originalName)
.saveName(saveName)
.size(size)
.build();
log.info("파일 저장 완료: {}", localFile.getCanonicalPath());
} catch (IllegalStateException | IOException e) {
throw new RuntimeException(e);
}
}
return dto;
}
}
FileController.java
package com.study.file_upload.api.controller;
import com.study.file_upload.api.service.FileService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RequiredArgsConstructor
@RestController
@Slf4j
public class FileController {
private final FileService fileService;
@PostMapping("/fileUpload")
public ResponseEntity<?> fileUpload(@RequestParam("uploadFile") MultipartFile uploadFile) {
log.info("FileController.fileUpload()");
fileService.save(uploadFile);
return ResponseEntity.ok("File upload OK");
}
}
FileViewController.java
package com.study.file_upload.api.controller;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@RequiredArgsConstructor
@Controller
public class FileViewController {
@GetMapping("/file-upload")
public String fileUpload(Model model) {
return "fileUpload";
}
}
fileUpload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>파일 업로드</title>
</head>
<body>
<div>
<form method="POST" enctype="multipart/form-data" action="/fileUpload">
<table>
<tr>
<td>File to upload:</td>
<td><input type="file" name="uploadFile" /></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Upload" /></td>
</tr>
</table>
</form>
</div>
<div>
<ul>
<li th:each="file: ${files}">
<a th:href="${file}" th:text="${file}"></a>
</li>
</ul>
</div>
</body>
</html>
'Framework > Springboot' 카테고리의 다른 글
PostgresSQL 사용시 엔티티의 Default 값 설정하기 (0) | 2024.02.09 |
---|---|
스프링부트로 이메일 인증 서비스 구현하기 (4) | 2024.02.04 |
스프링부트로 이메일 인증 서비스 구현하기 (0) | 2024.02.03 |
스프링부트로 이메일 인증 서비스 구현하기 (0) | 2024.01.31 |
스프링부트에서 html 템플릿 조회하기 (0) | 2024.01.30 |
댓글