Spring과 DB를 연동했으니 사진을 직접 업로드하는 기능을 구현해보려고 한다.
프로젝트를 진행할 때 이미지서버는 이미 구축되어 있었고, 에디터에서 이미지를 전달받아 S3 서버에 업로드하고 업로드한 이미지 URL을 다시 프론트로 보내주는 로직이 필요했다. (따라서 별도의 php서버나 Apache 라이브러리를 사용하지 않았다.)
* 이전글
스마트 에디터 2.0으로 게시판 만들기 - 2. Spring Boot/DB 연동하기(Backend)
* 목차
1. 스마트 에디터 2.0으로 게시판 만들기 - 스마트에디터 글 작성하기(Frontend)
2. 스마트 에디터 2.0으로 게시판 만들기 - Spring Boot/DB 연동하기(Backend)
3. 스마트 에디터 2.0으로 게시판 만들기 - 싱글사진 업로드하기
4. 스마트 에디터 2.0으로 게시판 만들기 - 멀티사진 업로드하기
5. 스마트 에디터 2.0으로 게시판 만들기 - 동영상 올리기
1. photo_uploader.html - jQuery 세팅하기
스마트에디터는 네이버에서 jindo 라이브러리를 이용하여 구현되어 있다. 처음에는 약간의 커스텀만 사용하여 이 라이브러리를 그대로 사용하려고 했으나 뭐가 문제인지 인코딩 에러와 온갖 에러가 펼쳐졌다. 어차피 서버는 이미 구축되어 있고 나는 프론트-백 간 이미지 전송로직만 필요했기에 결국 jQuery를 이용해서 직접 구현해서 사용하였다.
smarteditor 폴더 내의 photo_uploader.html에 jQuery cdn 경로를 입력해준다. 이 때 그대로 사용하면 Jindo와 충돌이 나기 때문에 충돌나지 않도록 설정을 해주고, 앞으로 jQuery를 사용할 경우엔 $가 아니라 jQuery3_4_1로 사용하기로 한다.
파일 위치 - /static/smarteditor/sample/photo_uploader/photo_uploader.html
<!-- 추가 -->
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script type="text/javascript">
window.jQuery3_4_1 = jQuery.noConflict(true);
</script>
<!-- 추가 -->
<script type="text/javascript" src="jindo.min.js" charset="utf-8"></script>
<script type="text/javascript" src="jindo.fileuploader.js" charset="utf-8"></script>
<script type="text/javascript" src="attach_photo.js" charset="utf-8"></script>
2. attach_photo.js 커스텀
다음은 스마트에디터의 핵심 로직이 담겨있는 attach_photo.js를 수정해주어야 한다.
수정해준 부분은 다음과 같다.
- uploadImage() - 수정
- customGeneralUpload() - 추가
- customHtml5Upload() - 추가
1) uploadImage()
기존에는 generalUpload(싱글 이미지)와 html5Upload(멀티 이미지) 를 호출해주고 있는데, 새로 추가한 customGeneralUpload(싱글 이미지)와 customHtml5Upload(멀티 이미지)를 호출하도록 수정해주었다.
/**
* 이미지 업로드 시작
* 확인 버튼 클릭하면 호출되는 msg
*/
function uploadImage (e){
if(!bSupportDragAndDropAPI){
// generalUpload();
customGeneralUpload();
} else{
// html5Upload();
customHtml5Upload();
}
}
싱글 이미지 업로드 함수(attach_photo.js에 새로 추가)
function customGeneralUpload() {
let imgFile = jQuery3_4_1("#uploadInputBox")[0].files[0];
let fdata = new FormData();
fdata.enctype = "multipart/form-data"
fdata.method = "POST"
fdata.append("filedata", imgFile)
jQuery3_4_1.ajax({
url: ""
, data: fdata
, method: "POST"
, enctype: "multipart/formdata; charset=utf-8"
, processData: false
, contentType: false
, cache: false
, success: function(data) {
let sfileURL = data.sFileURL
let sfileName = data.sFileName
let bNewLine = data.bNewLine
if(data.result == "200") {
let aResult = []
let obj = {
"bNewLine" : bNewLine
, "sfileURL" : sfileURL || ""
, "sfileName" : sfileName || ""
}
aResult.push(obj)
setPhotoToEditor(aResult) // 사진을 에디터에 세팅(기존함수)
goReadyMode() // 초기 사진업로드 준비상태로 되돌리기
window.close() // 사진 업로드 창 닫기
} else {
alert('사진 업로드를 실패하였습니다.')
}
}
, error: function(xhr, textStatus, errorThrown) {
alert('사진 업로드를 실패하였습니다.')
}
})
}
2) SmartEditor Vo 생성
이미지를 서버에 등록한 후 에디터에 이미지를 등록해주는 과정은 attach_photo.js 내의 메소드(setPhotoEditor)를 그대로 사용하였다. 이 때 경로(sFileURL)와 이름(sFileName), 개행여부(bNewLine)를 파라미터로 받기 때문에 model 객체에 해당 정보를 담아서 반환해줄 수 있도록 SmartEditor 객체를 생성해주었다.
package com.example.spring.thymeleaf.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class SmartEditor {
private String sFileURL;
private String sFileName;
private String bNewLine;
}
3) PostController - singleImageUpload() 생성
attach_photo.js의 customGeneralUpload()에서 전송한 이미지 파일을 받아서 처리해주는 Controller이다.
public View singleImageUpload(HttpServletRequest request
, @RequestParam SmartEditor smartEditor, ModelMap model)
throws UnsupportedEncodingException {
List<MultipartFile> imgFiles = new ArrayList<>();
Map<String, MultipartFile> fileMap = new HashMap<>();
if(request instanceof MultipartHttpServletRequest) {
MultipartHttpServletRequest req = (MultipartHttpServletRequest) request;
fileMap = req.getFileMap();
fileMap.forEach((key, value) -> {
imgFiles.add(value);
});
} else {
model.addAttribute("result", HttpStatus.BAD_REQUEST);
}
if(imgFiles.size() > 0) {
MultipartFile imgFile = imgFiles.get(0);
try {
SmartEditor result = postService.singleImageUpload(imgFile);
model.addAttribute("sFileURL", result.getSFileURL());
model.addAttribute("sFileName", result.getSFileName());
model.addAttribute("result", HttpStatus.OK);
} catch(Exception e) {
System.out.println(e.getMessage());
model.addAttribute("result", HttpStatus.BAD_REQUEST);
}
} else {
model.addAttribute("result", HttpStatus.BAD_REQUEST);
}
return new MappingJackson2JsonView();
}
4) PostServiceImpl.java
이미지 파일을 저장할 경로(filePath)를 임의로 지정해주고, 파일 정보를 담아서 전송한다. 이미지를 S3서버에 업로드하는 부분은 S3Upload 메소드에 별도로 구현하였다.
@Override
public SmartEditor singleImageUpload(MultipartFile imgFile) {
LocalDate today = LocalDate.now();
String fileName = imgFile.getOriginalFilename();
String filePath = "static/images/"+String.format("%02", today.getMonthValue())+"/";
String fileUrl = S3ImageUpload(imgFile, filePath);
SmartEditor smartEditor = new SmartEditor();
smartEditor.setSFileURL(fileUrl);
smartEditor.setSFileName(fileName);
smartEditor.setBNewLine(true);
return smartEditor;
}
'프로젝트' 카테고리의 다른 글
[AWS] AWS Parameter Store 조회 안될 때(Parameter 조회하는법) (0) | 2022.06.06 |
---|---|
[AWS S3] S3에 업로드한 이미지가 열리지 않고 다운로드 될 때 (0) | 2022.06.03 |
[VSCode] terminal color setting (+Spring error/warn 색깔 구분하기!) (1) | 2022.05.05 |
[Project] Naver SmartEditor 2.0으로 게시판만들기 - 2. MySQL/Spring Boot 연동하기 (0) | 2021.11.04 |
[Project] Naver SmartEditor 2.0으로 게시판만들기 - 1. 에디터 적용 (0) | 2021.11.04 |
댓글