본문 바로가기
프로젝트

[Naver] SmartEditor 2.0으로 게시판만들기 - 3. 싱글사진 업로드하기

by BeforB 2021. 11. 9.
728x90

 Spring과 DB를 연동했으니 사진을 직접 업로드하는 기능을 구현해보려고 한다.

 

 

프로젝트를 진행할 때 이미지서버는 이미 구축되어 있었고, 에디터에서 이미지를 전달받아 S3 서버에 업로드하고 업로드한 이미지 URL을 다시 프론트로 보내주는 로직이 필요했다. (따라서 별도의 php서버나 Apache 라이브러리를 사용하지 않았다.)

 

 

 

* 이전글

스마트 에디터 2.0으로 게시판 만들기 - 2. Spring Boot/DB 연동하기(Backend)

 

[Naver] SmartEditor 2.0으로 게시판만들기 - 2. MySQL/Spring Boot 연동하기

1탄에서는 Smart Editor 2.0 버전을 설치하여 단순 적용해보았다. 이번에는 MySQL과 Spring Boot을 연동하여 작성한 게시글을 DB에 전송해보려고 한다. 블로그용으로 새로 샘플을 만들고 JPA로 바꾸다보니

beforb.tistory.com

 

 

* 목차

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;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90

댓글