....
This commit is contained in:
parent
c5de7a3548
commit
9e4597890b
@ -2,10 +2,16 @@ package kr.lunaticbum.back.lun.controllers
|
|||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest
|
import jakarta.servlet.http.HttpServletRequest
|
||||||
import jakarta.servlet.http.HttpServletResponse
|
import jakarta.servlet.http.HttpServletResponse
|
||||||
|
import kr.lunaticbum.back.lun.model.FileSaveResult
|
||||||
|
import kr.lunaticbum.back.lun.model.ResponceResult
|
||||||
import kr.lunaticbum.back.lun.utils.LogService
|
import kr.lunaticbum.back.lun.utils.LogService
|
||||||
import kr.lunaticbum.back.lun.utils.getFileExtension
|
import kr.lunaticbum.back.lun.utils.getFileExtension
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
import org.springframework.beans.factory.annotation.Value
|
import org.springframework.beans.factory.annotation.Value
|
||||||
|
import org.springframework.core.io.Resource
|
||||||
|
import org.springframework.core.io.UrlResource
|
||||||
|
import org.springframework.http.MediaType
|
||||||
|
import org.springframework.http.ResponseEntity
|
||||||
import org.springframework.web.bind.annotation.*
|
import org.springframework.web.bind.annotation.*
|
||||||
import org.springframework.web.multipart.MultipartFile
|
import org.springframework.web.multipart.MultipartFile
|
||||||
import org.springframework.web.servlet.ModelAndView
|
import org.springframework.web.servlet.ModelAndView
|
||||||
@ -40,47 +46,63 @@ class BlogController() {
|
|||||||
private val resourceHandler: String? = null
|
private val resourceHandler: String? = null
|
||||||
|
|
||||||
|
|
||||||
|
@ResponseBody
|
||||||
|
@GetMapping("/post/images/{fileName}")
|
||||||
|
fun getImage(@PathVariable fileName : String) : Resource {
|
||||||
|
val imgUploadPath = ("file:" +uploadPath + File.separator + fileName)
|
||||||
|
return UrlResource.from(imgUploadPath)
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping("/post/imageUpload")
|
@PostMapping("/post/imageUpload")
|
||||||
fun postImage(@RequestPart("file") upload: MultipartFile, res: HttpServletResponse, req: HttpServletRequest) {
|
fun postImage(@RequestPart("file") upload: MultipartFile, res: HttpServletResponse, req: HttpServletRequest) : ResponseEntity<FileSaveResult> {
|
||||||
|
var lResultCode = 0
|
||||||
|
var lResultMsg = "Suscces"
|
||||||
var out: OutputStream? = null
|
var out: OutputStream? = null
|
||||||
var printWriter: PrintWriter? = null
|
var printWriter: PrintWriter? = null
|
||||||
|
var targetFile : File? = null
|
||||||
logService.log("imgUploadPath ${upload.originalFilename}")
|
logService.log("imgUploadPath ${upload.originalFilename}")
|
||||||
res.characterEncoding = "utf-8"
|
res.characterEncoding = "utf-8"
|
||||||
res.contentType = "text/html;charset=utf-8"
|
res.contentType = "text/html;charset=utf-8"
|
||||||
|
var uuid = UUID.randomUUID()
|
||||||
|
val extension: String = getFileExtension(upload.originalFilename) ?: ""
|
||||||
try {
|
try {
|
||||||
val uuid = UUID.randomUUID()
|
|
||||||
logService.log("imgUploadPath ${uuid.toString()}")
|
|
||||||
|
|
||||||
val extension: String = getFileExtension(upload.originalFilename) ?: ""
|
logService.log("imgUploadPath ${uuid.toString()}")
|
||||||
|
|
||||||
val bytes = upload.bytes
|
val bytes = upload.bytes
|
||||||
|
|
||||||
var f = File(uploadPath)
|
var f = File(uploadPath)
|
||||||
|
// logService.log("imgUploadPath ${f.parentFile.parentFile.parentFile.parentFile.absoluteFile}")
|
||||||
|
// logService.log("imgUploadPath ${f.parentFile.parentFile.parentFile.absoluteFile}")
|
||||||
|
// logService.log("imgUploadPath ${f.parentFile.parentFile.absoluteFile}")
|
||||||
|
// logService.log("imgUploadPath ${f.parentFile.absoluteFile}")
|
||||||
logService.log("imgUploadPath ${f.exists()}")
|
logService.log("imgUploadPath ${f.exists()}")
|
||||||
|
logService.log("imgUploadPath ${f.absolutePath}")
|
||||||
if (f.exists() == false) f.mkdirs()
|
if (f.exists() == false) f.mkdirs()
|
||||||
// 실제 이미지 저장 경로
|
// 실제 이미지 저장 경로
|
||||||
val imgUploadPath = (uploadPath + File.separator + uuid).toString() + "." + extension
|
val imgUploadPath = (uploadPath + File.separator + uuid).toString() + "." + extension
|
||||||
logService.log("imgUploadPath $imgUploadPath")
|
logService.log("imgUploadPath $imgUploadPath")
|
||||||
File(imgUploadPath).parentFile.mkdirs()
|
targetFile = File(imgUploadPath)
|
||||||
|
if(targetFile.parentFile.exists() == false)targetFile.parentFile.mkdirs()
|
||||||
|
|
||||||
// 이미지 저장
|
// 이미지 저장
|
||||||
out = FileOutputStream(imgUploadPath)
|
out = FileOutputStream(imgUploadPath)
|
||||||
out.write(bytes)
|
out.write(bytes)
|
||||||
out.flush()
|
out.flush()
|
||||||
|
|
||||||
// ckEditor 로 전송
|
// ckEditor 로 전송
|
||||||
printWriter = res.writer
|
// printWriter = res.writer
|
||||||
val callback = req.getParameter("CKEditorFuncNum")
|
// val callback = req.getParameter("CKEditorFuncNum")
|
||||||
val fileUrl = "/blog/post/image/$uuid.$extension"
|
// val fileUrl = "/blog/post/image/$uuid.$extension"
|
||||||
|
|
||||||
printWriter.println(
|
// printWriter.println(
|
||||||
("<script type='text/javascript'>"
|
// ("<script type='text/javascript'>"
|
||||||
+ "window.parent.CKEDITOR.tools.callFunction("
|
// + "window.parent.CKEDITOR.tools.callFunction("
|
||||||
+ callback + ",'" + fileUrl + "','이미지를 업로드하였습니다.')"
|
// + callback + ",'" + fileUrl + "','이미지를 업로드하였습니다.')"
|
||||||
+ "</script>")
|
// + "</script>")
|
||||||
)
|
// )
|
||||||
|
//
|
||||||
printWriter.flush()
|
// printWriter.flush()
|
||||||
logService.log("imgUploadPath $imgUploadPath")
|
logService.log("imgUploadPath $imgUploadPath")
|
||||||
logService.log("imgUploadPath ${File(imgUploadPath).exists()}")
|
logService.log("imgUploadPath ${File(imgUploadPath).exists()}")
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
@ -88,11 +110,17 @@ class BlogController() {
|
|||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
out?.close()
|
out?.close()
|
||||||
|
|
||||||
printWriter?.close()
|
printWriter?.close()
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val responce = ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(FileSaveResult().apply {
|
||||||
|
|
||||||
|
this.resultCode = lResultCode
|
||||||
|
this.resultMsg = lResultMsg
|
||||||
|
this.fileName = "$uuid.$extension"
|
||||||
|
})
|
||||||
|
return responce
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4,7 +4,12 @@ import lombok.Getter
|
|||||||
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
class ResponceResult {
|
open class ResponceResult {
|
||||||
var resultCode: Int = 0
|
var resultCode: Int = 0
|
||||||
var resultMsg: String? = null
|
var resultMsg: String? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
class FileSaveResult : ResponceResult() {
|
||||||
|
var fileName : String? = null
|
||||||
|
}
|
||||||
@ -5,6 +5,8 @@
|
|||||||
layout:decorate="~{layout/default_layout}">
|
layout:decorate="~{layout/default_layout}">
|
||||||
|
|
||||||
<th:block layout:fragment="head">
|
<th:block layout:fragment="head">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
<!-- TOAST UI Editor CDN(JS) -->
|
<!-- TOAST UI Editor CDN(JS) -->
|
||||||
<!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"/>-->
|
<!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"/>-->
|
||||||
<!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>-->
|
<!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>-->
|
||||||
@ -13,32 +15,50 @@
|
|||||||
<script type="text/javascript" src="https://uicdn.toast.com/editor/latest/toastui-editor-all.min.js"></script>
|
<script type="text/javascript" src="https://uicdn.toast.com/editor/latest/toastui-editor-all.min.js"></script>
|
||||||
<!-- TOAST UI Editor CDN(CSS) -->
|
<!-- TOAST UI Editor CDN(CSS) -->
|
||||||
<link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/toastui-editor.min.css" />
|
<link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/toastui-editor.min.css" />
|
||||||
|
<link rel="stylesheet" href="https://uicdn.toast.com/editor/latest/toastui-editor-dark.css" />
|
||||||
<title>Spring Boot</title>
|
<title>Spring Boot</title>
|
||||||
<script th:inline="javascript">
|
<script th:inline="javascript">
|
||||||
|
let editor
|
||||||
function onLoaded() {
|
function onLoaded() {
|
||||||
// const onChange = () => {
|
var h = document.querySelector('#content').getBoundingClientRect().height + 'px'
|
||||||
// const editorHtml = editor.getHTML();
|
editor = new toastui.Editor({
|
||||||
// setHtml(editorHtml);
|
|
||||||
// };
|
|
||||||
const editor = new toastui.Editor({
|
|
||||||
el: document.querySelector('#editor'),
|
el: document.querySelector('#editor'),
|
||||||
previewStyle: 'vertical',
|
previewStyle: 'tab',
|
||||||
height: '500px',
|
height: '500px',
|
||||||
|
width:'100%',
|
||||||
|
theme:'dark',
|
||||||
usageStatistics : false,
|
usageStatistics : false,
|
||||||
initialValue: "",
|
toolbar:null,
|
||||||
|
initialValue:
|
||||||
|
"# 제목 " +"\n" +
|
||||||
|
"평문 사이에 **볼드체** *이탤릭체*"+"\n" +
|
||||||
|
"~~어디쓰지~~"+"\n" +
|
||||||
|
"***"+"\n" +
|
||||||
|
"### 모라모라 " +"\n" +
|
||||||
|
"> 으흐흠..." +"\n" +
|
||||||
|
"* 쓸까?" +"\n" +
|
||||||
|
"1. 첫번째" +"\n" +
|
||||||
|
"* [x] 체크하자" +"\n" +
|
||||||
|
"* [ ] 체크하자" +"\n" +
|
||||||
|
" \|dd\|cc\|ff\|\n" +
|
||||||
|
" \|\-\-\-\|\-\-\-\|\-\-\-\|\n" +
|
||||||
|
" \|aa\|s\|s\|" +"\n" +
|
||||||
|
"[링크다](https://youtube.com)" +"\n" +
|
||||||
|
"`var test = 'real test'`" +"\n" +
|
||||||
|
"```\n" +
|
||||||
|
"let test= = 'real test'\n" +
|
||||||
|
"```"
|
||||||
|
,
|
||||||
|
initialEditType:"wysiwyg",
|
||||||
// events : {
|
// events : {
|
||||||
// change : this.onChange
|
// change : this.onChange
|
||||||
// },
|
// },
|
||||||
hooks: {
|
hooks: {
|
||||||
addImageBlobHook: (blob, callback) => {
|
addImageBlobHook: (blob, callback) => {
|
||||||
// blob : Java Script 파일 객체
|
|
||||||
//console.log(blob);
|
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append('file', blob);
|
formData.append('file', blob);
|
||||||
|
|
||||||
let url = '/files/';
|
let url = 'blog/post/images/';
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
enctype: 'multipart/form-data',
|
enctype: 'multipart/form-data',
|
||||||
@ -50,17 +70,10 @@
|
|||||||
cache: false,
|
cache: false,
|
||||||
timeout: 600000,
|
timeout: 600000,
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
//console.log('ajax 이미지 업로드 성공');
|
|
||||||
url += data.fileName;
|
url += data.fileName;
|
||||||
fileIds += data.id + ",";
|
|
||||||
// callback : 에디터(마크다운 편집기)에 표시할 텍스트, 뷰어에는 imageUrl 주소에 저장된 사진으로 나옴
|
|
||||||
// 형식 : 
|
|
||||||
callback(url, '사진 대체 텍스트 입력');
|
callback(url, '사진 대체 텍스트 입력');
|
||||||
},
|
},
|
||||||
error: function (e) {
|
error: function (e) {
|
||||||
//console.log('ajax 이미지 업로드 실패');
|
|
||||||
//console.log(e.abort([statusText]));
|
|
||||||
|
|
||||||
callback('image_load_fail', '사진 대체 텍스트 입력');
|
callback('image_load_fail', '사진 대체 텍스트 입력');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -68,6 +81,9 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function save() {
|
||||||
|
console.log(editor.getMarkdown())
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<link th:href="@{/css/common.css}" rel="stylesheet" />
|
<link th:href="@{/css/common.css}" rel="stylesheet" />
|
||||||
<script type="text/javascript" th:src="@{/js/common.js}"></script>
|
<script type="text/javascript" th:src="@{/js/common.js}"></script>
|
||||||
@ -75,12 +91,17 @@
|
|||||||
</th:block>
|
</th:block>
|
||||||
<body onload="onLoaded()">
|
<body onload="onLoaded()">
|
||||||
<th:block layout:fragment="header" th:include="@{/fragments/header}"></th:block>
|
<th:block layout:fragment="header" th:include="@{/fragments/header}"></th:block>
|
||||||
<div layout:fragment='content' class='content' id='content'>
|
<div layout:fragment='content' class='content' id='content' style="padding: 10px">
|
||||||
<div id="editor">
|
<input id="title_layer" style="width:100%; height:50px; font-size:30px; border-width: 1px; align-content: center; margin: 10px"/>
|
||||||
|
<div id="editor" style="width:90%; font-size:15px; border-width: 0px; align-content: center"></div>
|
||||||
</div>
|
<div id="hashtag_layer">
|
||||||
|
<select style="width:40%; height:30px; font-size:15px; border-width: 0px"> </select>
|
||||||
|
<input id="hashtag" style="width:40%; height:30px; font-size:15px; border-width: 0px"/>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="controll_layer" style="width: 100%">
|
||||||
|
<button onclick="save()">asdsad</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<th:block layout:fragment="footer" th:include="@{/fragments/footer}"></th:block>
|
<th:block layout:fragment="footer" th:include="@{/fragments/footer}"></th:block>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Loading…
x
Reference in New Issue
Block a user