Image의 모델링이 완료되었으니, 다음으로는 서버에 Image를 전송하여 저장하도록 만들어주어야 한다.
우선 ImageController로 가서 업로드할 컨트롤러를 만들어주자.
package com.cos.photogramstart.web;
import com.cos.photogramstart.config.PrincipalDetails;
import com.cos.photogramstart.service.ImageService;
import com.cos.photogramstart.web.dto.Image.ImageUploadDto;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@RequiredArgsConstructor
@Controller
public class ImageController {
private final ImageService imageService;
@GetMapping({"/", "/image/story"})
public String story() { //기본페이지
return "image/story";
}
@GetMapping("/image/popular")
public String popular() { //인기페이지
return "image/popular";
}
@GetMapping("/image/upload")
public String upload() { //사진 등록을 위한 페이지
return "image/upload";
}
@PostMapping("/image")
public String imageUpload(ImageUploadDto imageUploadDto,
@AuthenticationPrincipal PrincipalDetails principalDetails) {
//서비스 호출
imageService.사진업로드(imageUploadDto, principalDetails);
return "redirect:/user/"+principalDetails.getUser().getId();
}
}
-> 이 '메서드'는 어떤 '매개변수'를 받아야 할까?
-> 당연히 Image에서 만든 데이터를 받아주어야 하는데, Image오브젝트와는 다른 정보를 받을것이다.
바로 PostImageUrl인데, 이 컨트롤러에서 우리는 url(경로)가 아닌 'Image 파일'을 받을것이다.
때문에 Dto를 따로 만들어주어야 한다.
Dto/image 경로에 ImageUploadDto 클래스를 만들어주자.
Image를 업로드할때, 두개의 input태그인 '사진파일'과 '사진설명'에 관한 데이터를 받아주자.
<!--사진업로드 Form-->
<form class="upload-form" action="/image" method="post" enctype="multipart/form-data">
<input type="file" name="file" onchange="imageChoose(this)"/>
<div class="upload-img">
<img src="/images/person.jpeg" alt="" id="imageUploadPreview" />
</div>
<!--사진설명 + 업로드버튼-->
<div class="upload-form-detail">
<input type="text" placeholder="사진설명" name="caption" />
<button class="cta blue">업로드</button>
</div>
<!--사진설명end-->
package com.cos.photogramstart.web.dto.Image;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
@Data
public class ImageUploadDto {
private MultipartFile file;
private String caption;
}
사진파일의 타입은 MultipartFile로 받아주면된다
MultipartFile로 받아주면 여러가지 타입의 파일을 모두 받아줄 수 있기 때문이다.
가령 jpg, jpeg, png, gif처럼 타입이 나누어져 있는데, 이걸 모두 받아줄 수 있다.
Dto를 만들어주었으니 Controller로 돌아가서 이 Dto를 '매개변수'로 받아주자.
@PostMapping("/image")
public String imageUpload(ImageUploadDto imageUploadDto,
@AuthenticationPrincipal PrincipalDetails principalDetails) {
//서비스 호출
imageService.사진업로드(imageUploadDto, principalDetails);
return "redirect:/user/"+principalDetails.getUser().getId();
}
}
그리고 또 받아주어야 하는 정보는 누가 올렸는지에 대한 '세션정보'도 있다
return 해줄 페이지는 Image를 올린 user를 찾아가야 한다.
Controller는 얼추 완성되었으니 , ImageUpload 로직을 담당할 Service를 만들어주자
package com.cos.photogramstart.service;
import com.cos.photogramstart.config.PrincipalDetails;
import com.cos.photogramstart.domain.Image.ImageRepository;
import com.cos.photogramstart.web.dto.Image.ImageUploadDto;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
@RequiredArgsConstructor
@Service
public class ImageService {
private final ImageRepository imageRepository;
@Value("${file.path}")
private String uploadFolder = "c:/workspace/springbootwork/upload/";
public void 사진업로드(ImageUploadDto imageUploadDto, PrincipalDetails principalDetails) {
UUID uuid = UUID.randomUUID(); //범용 고유 식별자
String imageFileName = uuid+"_"+ imageUploadDto.getFile().getOriginalFilename(); //1.jpg
System.out.println("이미지 파일 이름 : " + imageFileName);
Path imageFilePath = Paths.get(uploadFolder+imageFileName);
//통신, I/O -> 예외가 발생할 수 있다.
try {
Files.write(imageFilePath, imageUploadDto.getFile().getBytes());
} catch(Exception e) {
e.printStackTrace();
}
}
}
-> 이제 Controller로 돌아가서 Service를 DI해주고 메서드를 호출해보자
@PostMapping("/image")
public String imageUpload(ImageUploadDto imageUploadDto,
@AuthenticationPrincipal PrincipalDetails principalDetails) {
//서비스 호출
imageService.사진업로드(imageUploadDto, principalDetails);
return "redirect:/user/"+principalDetails.getUser().getId();
}
}
-> Controller는 완성되었으니, ImageUpload 로직을 완성하러 가보자
-> 혼선을 방지하기 위해 우리가 사용할 기술은 UUID(범용 고유 식별자)이다
UUID(Universally Unique IDentifier)는 고유성(Unique)가 보장하는 id를 만들 수 있게 해주는 기술이다
128비트의 숫자로써, 총 32자리의 16진수의 숫자를 8-4-4-4-12 자리로 하이픈이 추가되서 구분한다. 적용시켜보자
package com.cos.photogramstart.service;
import com.cos.photogramstart.config.PrincipalDetails;
import com.cos.photogramstart.domain.Image.ImageRepository;
import com.cos.photogramstart.web.dto.Image.ImageUploadDto;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;
@RequiredArgsConstructor
@Service
public class ImageService {
private final ImageRepository imageRepository;
//6. 이미지가 저장되는 경로 호출하기
@Value("${file.path}")
private String uploadFolder = "c:/workspace/springbootwork/upload/";
public void 사진업로드(ImageUploadDto imageUploadDto, PrincipalDetails principalDetails) {
//2. UUID 객체를 생성한다
UUID uuid = UUID.randomUUID(); //범용 고유 식별자
//1. 업로드 되는 원본 파일명을 imageFileName이라고 지정한다.
//3. UUID를 더한 값으로 지정한다
String imageFileName = uuid+"_"+ imageUploadDto.getFile().getOriginalFilename(); //1.jpg
//4. UUID가 적용된 파일명 확인하기
System.out.println("이미지 파일 이름 : " + imageFileName);
//5. Image 저장 경로 확인하기
Path imageFilePath = Paths.get(uploadFolder+imageFileName); //이미지경로
//7. 파일을 업로드하기
//통신, I/O -> 예외가 발생할 수 있다.
try {
Files.write(imageFilePath, imageUploadDto.getFile().getBytes());
} catch(Exception e) {
e.printStackTrace();
}
}
}
server:
port: 8080
servlet:
context-path: /
encoding:
charset: utf-8
enabled: true
spring:
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
datasource:
driver-class-name: org.mariadb.jdbc.Driver
url: jdbc:mariadb://localhost:3306/photogrammmmm?serverTimezone=Asia/Seoul
username: root
password: 12341234
jpa:
open-in-view: true
hibernate:
ddl-auto: update
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
show-sql: true
servlet:
multipart:
enabled: true
max-file-size: 2MB
security:
user:
name: test
password: 1234
file:
# path: C:/workspace/springbootwork/upload/
path: /Users/jeonghyunlee/Desktop/EaszUp-Springboot-Photogram-Start/upload/
이렇게 완성된 path를 file에 업로드해주자
'파일업로드'를 try-catch로 묶는 이유는 통신이나 I/O가 진행될때, '예외'가 발생할 수 있기 때문이다.
가령 , 1/jpg파일을 불러오는 요청을 할때, 1.jpa파일이 없을수도 있기 때문이다.
우선 Service는 여기까지 만들고, upload form태그에 action을 걸어주고 테스트해보자.
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ include file="../layout/header.jsp" %>
<!--사진 업로드페이지 중앙배치-->
<main class="uploadContainer">
<!--사진업로드 박스-->
<section class="upload">
<!--사진업로드 로고-->
<div class="upload-top">
<a href="home.html" class="">
<img src="/images/logo.jpg" alt="">
</a>
<p>사진 업로드</p>
</div>
<!--사진업로드 로고 end-->
<!--사진업로드 Form-->
<form class="upload-form" action="/image" method="post" enctype="multipart/form-data">
<input type="file" name="file" onchange="imageChoose(this)"/>
<div class="upload-img">
<img src="/images/person.jpeg" alt="" id="imageUploadPreview" />
</div>
<!--사진설명 + 업로드버튼-->
<div class="upload-form-detail">
<input type="text" placeholder="사진설명" name="caption" />
<button class="cta blue">업로드</button>
</div>
<!--사진설명end-->
</form>
<!--사진업로드 Form-->
</section>
<!--사진업로드 박스 end-->
</main>
<br/><br/>
<script src="/js/upload.js" ></script>
<%@ include file="../layout/footer.jsp" %>
'메타코딩 SNS프로젝트' 카테고리의 다른 글
28. 프로필 페이지 - Image 파일경로를 DB에 INSERT하기 (0) | 2022.06.21 |
---|---|
27. 프로필 페이지 - Image 업로드 경로를 프로젝트 외부에 두는 이유 (0) | 2022.06.20 |
25. 프로필페이지 - Image 모델링하기 (0) | 2022.06.20 |
24. 구독하기 - 글로벌 예외 처리하기, API 주소 시큐리티 설정하기 (0) | 2022.06.20 |
23. 구독하기 - 구독, 구독취소 API 만들기 (0) | 2022.06.20 |