-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2dd0643
commit 0510b51
Showing
10 changed files
with
594 additions
and
96 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,383 @@ | ||
# 帖子发图功能 | ||
|
||
之前的懒不能偷。。现在应测试需求补上发帖时的图片功能 | ||
|
||
修改 publish 和 update 界面的逻辑,增加存储图片的逻辑 | ||
|
||
[参考](https://itmtx.cn/article/199?columnId=12) | ||
|
||
|
||
|
||
1. SecurityConfig新增跨域解决: | ||
|
||
```java | ||
@Bean | ||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { | ||
// 禁用X-Frame-Options | ||
http.headers(headers -> headers | ||
.frameOptions(frameOptions -> frameOptions.disable()) | ||
); | ||
} | ||
``` | ||
|
||
2. CommunityUtil新返回json接口: | ||
|
||
```java | ||
// editor.md 要求返回的 JSON 字符串格式 | ||
public static String getEditorMdJSONString(int success, String message, String url) { | ||
JSONObject json = new JSONObject(); | ||
json.put("success", success); | ||
json.put("message", message); | ||
json.put("url", url); | ||
return json.toJSONString(); | ||
} | ||
``` | ||
|
||
3. DiscussPostController新增: | ||
|
||
在这之前,先配置路径: | ||
|
||
develop: | ||
|
||
``` | ||
community.path.editormdUploadPath=c:/Users/15170/Desktop/community/data | ||
``` | ||
|
||
produce: | ||
|
||
``` | ||
community.path.editormdUploadPath=/tmp/uploads/mdPic | ||
``` | ||
|
||
```java | ||
// 处理帖子上传图片 | ||
@RequestMapping(path = "/uploadMdPic", method = RequestMethod.POST) | ||
@ResponseBody | ||
public String uploadMdPic(@RequestParam(value = "editormd-image-file", required = false) MultipartFile file) { | ||
|
||
String url = null; // 图片访问地址 | ||
try { | ||
// 获取上传文件的名称 | ||
String trueFileName = file.getOriginalFilename(); | ||
String suffix = trueFileName.substring(trueFileName.lastIndexOf(".")); | ||
String fileName = CommunityUtil.genUUID() + suffix; | ||
|
||
// 图片存储路径 | ||
File dest = new File(editormdUploadPath + "/" + fileName); | ||
if (!dest.getParentFile().exists()) { | ||
dest.getParentFile().mkdirs(); | ||
} | ||
|
||
// 保存图片到存储路径 | ||
file.transferTo(dest); | ||
|
||
// 图片访问地址 | ||
url = domain + contextPath + "/upload/" + fileName; | ||
System.out.println(url); | ||
} catch (Exception e) { | ||
e.printStackTrace(); | ||
return CommunityUtil.getEditorMdJSONString(0, "上传失败", url); | ||
} | ||
return CommunityUtil.getEditorMdJSONString(1, "上传成功", url); | ||
} | ||
|
||
// 帖子读取图片 | ||
@RequestMapping(path = "/upload/{fileName}", method = RequestMethod.GET) | ||
public void getMdPic(@PathVariable("fileName") String fileName, HttpServletResponse response) { | ||
// 服务器存放路径 | ||
String filePath = editormdUploadPath + "/" + fileName; | ||
|
||
File file = new File(filePath); | ||
if (!file.exists()) { | ||
System.out.println("文件不存在: " + filePath); | ||
response.setStatus(HttpServletResponse.SC_NOT_FOUND); | ||
return; | ||
} | ||
|
||
String suffix = fileName.substring(fileName.lastIndexOf(".") + 1); | ||
|
||
// 响应文件 | ||
response.setContentType("image/" + suffix); | ||
try ( | ||
OutputStream os = response.getOutputStream(); | ||
FileInputStream fis = new FileInputStream(file); | ||
) { | ||
byte[] buffer = new byte[1024]; | ||
int b; | ||
while ((b = fis.read(buffer)) != -1) { | ||
os.write(buffer, 0, b); | ||
} | ||
} catch (IOException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
``` | ||
|
||
3. 前端 | ||
|
||
```html | ||
<script type="text/javascript"> | ||
var testEditor; | ||
$(function() { | ||
testEditor = editormd("test-editormd", { | ||
width: "90%", | ||
height: 640, | ||
syncScrolling: "single", | ||
path: "../editor-md/lib/", | ||
saveHTMLToTextarea: true, // 方便post提交表单 | ||
placeholder: "欢迎来到帖子发布界面~ 本论坛支持 Markdown/非Markdown 格式的帖子~", | ||
// 上传图片 | ||
imageUpload : true, | ||
imageFormats : ["jpg", "jpeg", "gif", "png", "bmp", "webp"], | ||
imageUploadURL : CONTEXT_PATH + "/discuss/uploadMdPic", // 后端上传图片的服务地址 | ||
onload : function() {} | ||
}); | ||
</script> | ||
``` | ||
注意:这里需要修改官方文件的/plugins/image-dialog/image-dialog.js, 参考[博客](https://blog.csdn.net/ELOVINFG/article/details/103048813) | ||
如下: | ||
```javascript | ||
(function() { | ||
var factory = function (exports) { | ||
var pluginName = "image-dialog"; | ||
exports.fn.imageDialog = function() { | ||
var _this = this; | ||
var cm = this.cm; | ||
var lang = this.lang; | ||
var editor = this.editor; | ||
var settings = this.settings; | ||
var cursor = cm.getCursor(); | ||
var selection = cm.getSelection(); | ||
var imageLang = lang.dialog.image; | ||
var classPrefix = this.classPrefix; | ||
var iframeName = classPrefix + "image-iframe"; | ||
var dialogName = classPrefix + pluginName, dialog; | ||
cm.focus(); | ||
var loading = function(show) { | ||
var _loading = dialog.find("." + classPrefix + "dialog-mask"); | ||
_loading[(show) ? "show" : "hide"](); | ||
}; | ||
if (editor.find("." + dialogName).length < 1) | ||
{ | ||
var guid = (new Date).getTime(); | ||
var action = settings.imageUploadURL + (settings.imageUploadURL.indexOf("?") >= 0 ? "&" : "?") + "guid=" + guid; | ||
if (settings.crossDomainUpload) | ||
{ | ||
action += "&callback=" + settings.uploadCallbackURL + "&dialog_id=editormd-image-dialog-" + guid; | ||
} | ||
var dialogContent = ( (settings.imageUpload) ? "<form action=\"#\" target=\"" + iframeName + "\" method=\"post\" enctype=\"multipart/form-data\" class=\"" + classPrefix + "form\">" : "<div class=\"" + classPrefix + "form\">" ) + | ||
( (settings.imageUpload) ? "<iframe name=\"" + iframeName + "\" id=\"" + iframeName + "\" guid=\"" + guid + "\"></iframe>" : "" ) + | ||
"<label>" + imageLang.url + "</label>" + | ||
"<input type=\"text\" data-url />" + (function(){ | ||
return (settings.imageUpload) ? "<div class=\"" + classPrefix + "file-input\">" + | ||
"<input type=\"file\" name=\"" + classPrefix + "image-file\" id=\"" + classPrefix + "image-file\" accept=\"image/*\" />" + | ||
"<input type=\"submit\" value=\"" + imageLang.uploadButton + "\" />" + | ||
"</div>" : ""; | ||
})() + | ||
"<br/>" + | ||
"<label>" + imageLang.alt + "</label>" + | ||
"<input type=\"text\" value=\"" + selection + "\" data-alt />" + | ||
"<br/>" + | ||
"<label>" + imageLang.link + "</label>" + | ||
"<input type=\"text\" value=\"http://\" data-link />" + | ||
"<br/>" + | ||
( (settings.imageUpload) ? "</form>" : "</div>"); | ||
dialog = this.createDialog({ | ||
title : imageLang.title, | ||
width : (settings.imageUpload) ? 465 : 380, | ||
height : 254, | ||
name : dialogName, | ||
content : dialogContent, | ||
mask : settings.dialogShowMask, | ||
drag : settings.dialogDraggable, | ||
lockScreen : settings.dialogLockScreen, | ||
maskStyle : { | ||
opacity : settings.dialogMaskOpacity, | ||
backgroundColor : settings.dialogMaskBgColor | ||
}, | ||
buttons : { | ||
enter : [lang.buttons.enter, function() { | ||
var url = this.find("[data-url]").val(); | ||
var alt = this.find("[data-alt]").val(); | ||
var link = this.find("[data-link]").val(); | ||
if (url === "") | ||
{ | ||
alert(imageLang.imageURLEmpty); | ||
return false; | ||
} | ||
var altAttr = (alt !== "") ? " \"" + alt + "\"" : ""; | ||
if (link === "" || link === "http://") | ||
{ | ||
cm.replaceSelection(""); | ||
} | ||
else | ||
{ | ||
cm.replaceSelection("[](" + link + altAttr + ")"); | ||
} | ||
if (alt === "") { | ||
cm.setCursor(cursor.line, cursor.ch + 2); | ||
} | ||
this.hide().lockScreen(false).hideMask(); | ||
//删除对话框 | ||
this.remove(); | ||
return false; | ||
}], | ||
cancel : [lang.buttons.cancel, function() { | ||
this.hide().lockScreen(false).hideMask(); | ||
//删除对话框 | ||
this.remove(); | ||
return false; | ||
}] | ||
} | ||
}); | ||
dialog.attr("id", classPrefix + "image-dialog-" + guid); | ||
if (!settings.imageUpload) { | ||
return ; | ||
} | ||
var fileInput = dialog.find("[name=\"" + classPrefix + "image-file\"]"); | ||
fileInput.bind("change", function() { | ||
var fileName = fileInput.val(); | ||
var isImage = new RegExp("(\\.(" + settings.imageFormats.join("|") + "))$", "i"); // /(\.(webp|jpg|jpeg|gif|bmp|png))$/ | ||
if (fileName === "") | ||
{ | ||
alert(imageLang.uploadFileEmpty); | ||
return false; | ||
} | ||
if (!isImage.test(fileName)) | ||
{ | ||
alert(imageLang.formatNotAllowed + settings.imageFormats.join(", ")); | ||
return false; | ||
} | ||
loading(true); | ||
var submitHandler = function() { | ||
var uploadIframe = document.getElementById(iframeName); | ||
uploadIframe.onload = function() { | ||
loading(false); | ||
var formData = new FormData(); | ||
formData.append("editormd-image-file",$("#editormd-image-file")[0].files[0]); | ||
var action = settings.imageUploadURL + (settings.imageUploadURL.indexOf("?") >= 0 ? "&" : "?") + "guid=" + guid; | ||
let token = $("meta[name= '_csrf']").attr("content"); | ||
let header = $("meta[name= '_csrf_header']").attr("content"); | ||
$(document).ajaxSend(function (e, xhr, options){ | ||
xhr.setRequestHeader(header, token); | ||
}); | ||
$.ajax({ | ||
type:"post", | ||
url:action, | ||
data:formData, | ||
dataType:"json", | ||
async:false, | ||
processData : false, // 使数据不做处理 | ||
contentType : false, // 不要设置Content-Type请求头 | ||
success:function(data){ | ||
// 成功拿到结果放到这个函数 data就是拿到的结果 | ||
console.log(data); | ||
if(data.success == 1){ | ||
console.log(data.message); | ||
dialog.find("[data-url]").val(data.url); | ||
}else{ | ||
alert(data.message); | ||
} | ||
}, | ||
}); | ||
return false; | ||
}; | ||
}; | ||
dialog.find("[type=\"submit\"]").bind("click", submitHandler).trigger("click"); | ||
}); | ||
} | ||
dialog = editor.find("." + dialogName); | ||
dialog.find("[type=\"text\"]").val(""); | ||
dialog.find("[type=\"file\"]").val(""); | ||
dialog.find("[data-link]").val("http://"); | ||
this.dialogShowMask(dialog); | ||
this.dialogLockScreen(); | ||
dialog.show(); | ||
}; | ||
}; | ||
// CommonJS/Node.js | ||
if (typeof require === "function" && typeof exports === "object" && typeof module === "object") | ||
{ | ||
module.exports = factory; | ||
} | ||
else if (typeof define === "function") // AMD/CMD/Sea.js | ||
{ | ||
if (define.amd) { // for Require.js | ||
define(["editormd"], function(editormd) { | ||
factory(editormd); | ||
}); | ||
} else { // for Sea.js | ||
define(function(require) { | ||
var editormd = require("./../../editormd"); | ||
factory(editormd); | ||
}); | ||
} | ||
} | ||
else | ||
{ | ||
factory(window.editormd); | ||
} | ||
})(); | ||
``` | ||
注意:如果一直显示图片404,应该是虚拟路径映射的问题,springboot为了保护服务器,会隐藏真实路径 | ||
只要在WebMvcConfig下增加: | ||
```java | ||
@Value("${community.path.editormdUploadPath}") | ||
private String editormdUploadPath; | ||
@Override | ||
public void addResourceHandlers(ResourceHandlerRegistry registry) { | ||
// 将上传路径映射到虚拟路径 | ||
registry.addResourceHandler("/upload/**").addResourceLocations("file:" + editormdUploadPath + "/"); | ||
} | ||
``` |
Oops, something went wrong.