domain 추가
(첨부파일: Attachment)
@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name = "attachment")
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Attachment {
public Attachment(Long id) {
this.id = id;
}
public Attachment(String fileName, String filePath, long fileSize, String fileContentType) {
this.fileName = fileName;
this.filePath = filePath;
this.fileSize = fileSize;
this.fileContentType = fileContentType;
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@EqualsAndHashCode.Include
private Long id;
@Column(updatable = false, nullable = false)
private String fileName; // 원본 파일명
@Column(updatable = false, nullable = false, unique = true)
private String filePath; // 실제 저장된 파일명
@Column(updatable = false)
private String fileContentType;
@Column(updatable = false)
private long fileSize;
@PreRemove
public void onRemove() {
File file = new File(filePath);
FileUtils.deleteQuietly(file);
}
@JsonIgnore
public String getEncodedFileName() throws UnsupportedEncodingException {
return URLEncoder.encode(this.fileName, "UTF-8").replace("+", "%20");
}
public String getFileSizeText() {
float size = fileSize;
String unit = "Byte";
if (size >= 1024) {
unit = "KB";
size /= 1024;
if (size >= 1024) {
unit = "MB";
size /= 1024;
}
}
return String.format("%d%s", (int) size, unit);
}
public String getIconPath() {
String type = "file";
if(fileContentType.toLowerCase().startsWith("image")) {
type = "img";
} else {
String lowerCaseName = fileName.toLowerCase();
if(lowerCaseName.endsWith("doc") || lowerCaseName.endsWith("docx")) {
type = "doc";
} else if(lowerCaseName.endsWith("hwp")) {
type = "hwp";
} else if(lowerCaseName.endsWith("pdf")) {
type = "pdf";
} else if(lowerCaseName.endsWith("xls") || lowerCaseName.endsWith("xlsx")) {
type = "xl";
} else if(lowerCaseName.endsWith("zip")) {
type = "zip";
} else if(lowerCaseName.endsWith("ppt") || lowerCaseName.endsWith("pptx")) {
type = "ppt";
}
}
return "static/img/files/" + String.format("icon-%s.png", type);
}
}
service추가
(파일 업로드 관련)
@Service
@RequiredArgsConstructor
public class FileUploadService {
public static final String PATH_LOGOS = "logos/";
public static final String PATH_ATTACHMENTS = "attachments/";
@Value("${spring.servlet.multipart.location}")
private String rootPath;
public Attachment upload(MultipartFile file, String destinationPath) throws IOException {
if (file == null || file.isEmpty()) {
return null;
}
String fileName = file.getOriginalFilename();
String fileExtension = FilenameUtils.getExtension(fileName);
if (StringUtils.isBlank(fileExtension)) {
return null;
}
File destinationFile;
String destinationFileName;
do {
destinationFileName = destinationPath + FileUtil.getRandomFilename(fileExtension);
destinationFile = new File(rootPath + destinationFileName);
} while (destinationFile.exists());
//noinspection ResultOfMethodCallIgnored
destinationFile.getParentFile().mkdirs();
file.transferTo(destinationFile);
Attachment attachment = new Attachment();
//이미지인 경우 리사이징
if (file.getContentType() != null && file.getContentType().contains("image")) {
BufferedImage image = ImageIO.read(destinationFile);
double maxThumbnailWidth = 1280.0;
double thumbnailRatio =
maxThumbnailWidth > image.getWidth() ? 1 : maxThumbnailWidth / image.getWidth();
//이미지 사이즈 변경
BufferedImage resizedImage = resize(image, thumbnailRatio, Image.SCALE_FAST);
ImageIO.write(resizedImage, "JPEG", destinationFile);
}
attachment.setFileName(file.getOriginalFilename());
attachment.setFilePath(FilenameUtils.normalize(destinationFile.getAbsolutePath(), true));
attachment.setFileContentType(file.getContentType());
attachment.setFileSize(file.getSize());
return attachment;
}
public Attachment uploadFile(MultipartFile file) throws IOException {
return upload(file, PATH_ATTACHMENTS);
}
public Attachment uploadLogo(MultipartFile file) throws IOException {
return upload(file, PATH_LOGOS);
}
private BufferedImage resize(BufferedImage beforeImage, double ratio, int imageScale) {
int newW = (int) (beforeImage.getWidth() * ratio);
int newH = (int) (beforeImage.getHeight() * ratio);
Image tmp = beforeImage.getScaledInstance(newW, newH, imageScale);
BufferedImage dimg = new BufferedImage(newW, newH, beforeImage.getType());
Graphics2D g2d = dimg.createGraphics();
g2d.drawImage(tmp, 0, 0, null);
g2d.dispose();
return dimg;
}
}
파일을 첨부할 controller 수정
@PostMapping("/save")
public String save(@ModelAttribute("project") Project project, BindingResult result,
MultipartFile[] files) {
if (!result.hasErrors()) {
if (files != null) {
for (MultipartFile file : files) {
try {
project.getAttachments().add(fileUploadService.uploadFile(file));
} catch (IOException e) {
e.printStackTrace();
}
}
}
projectService.save(project);
return "project/edit";
}
return null;
}
화면에 폼 추가하기
(project/edit)
<form method="post" th:action="|@{/project/save}|" th:object="${project}" enctype="multipart/form-data">
<!-- 첨부파일-->
<div class="d-flex mt-3 mb-2 justify-content-between">
<label class="form-label m-0 mr-2">Attachment</label>
<div>
<label for="input-file" id="addFile" class="input-file-button">Upload</label>
<input type="file" id="input-file" name="files" style="display: none;" multiple/>
</div>
</div>
</form>
enctype="multipart/form-data" 이게 중요하다! 이걸 표시해줘야 파일이란 것을 알 수 있음!!
본인의 프로젝트에 맞게 설정을 잘하고 저장버튼을 누르면 파일이 업로드 됨을 볼 수 있다.
'Web > Spring' 카테고리의 다른 글
[Login구현] login-logout구현(setting) (0) | 2021.08.10 |
---|---|
[MultipartFile] 첨부파일 다운로드 (0) | 2021.08.06 |
[properties] server.port vs server.http.port (0) | 2021.08.06 |
[ERROR] 유의해야 할 점 (0) | 2021.08.06 |
[Annotation] @PathVariable (0) | 2021.08.06 |