CKeditor图片上传配置和自定义文件上传插件
CKeditor图片上传配置和自定义文件上传插件
一、图片上传的配置
在CKeditor的config.js文件中添加图片上传的配置
CKEDITOR.editorConfig = function( config ) {
config.plugins =
'basicstyles,' +
'bidi,' +
'blockquote,' +
'clipboard,' +
'colorbutton,' +
'colordialog,'
'tableselection,' +
// 其他的一些插件省略
'tabletools,' +
'toolbar,' +
'undo,' +
'uploadimage,' +
'wysiwygarea';
// %REMOVE_END%
/** 上传图片的配置 start **/
config.image_previewText=' ';
config.filebrowserUploadMethod = 'form';
// 配置上传图片请求地址
config.filebrowserImageUploadUrl="/api/common/uploadImage";
/** 上传图片的配置 end **/
};
后台使用的是springboot,上传图片的后台代码
controller:
@RestController
@RequestMapping(value = "/api/common")
public class CommonApi {
/** 图片临时存储路径 **/
@Value("${img.temp.save.path}")
private String imgTempSavePath;
/** 图片的访问路径 **/
@Value("${img.visit.path}")
private String imgVisitPath;
private final static Logger LOG = LoggerFactory.getLogger(CommonApi.class);
@Autowired
private TranFileInfoService tranFileInfoService;
/**
* 上传图片
*
* @param file
*/
@RequestMapping(value = "/uploadImage")
public void uploadImage(@RequestParam("upload") MultipartFile[] file, HttpServletRequest request,
HttpServletResponse response, HttpSession session) {
response.setCharacterEncoding("UTF-8");
PrintWriter out = null;
// CKEditor提交的很重要的一个参数 ,回调函数的序号
String callback = request.getParameter("CKEditorFuncNum");
try {
out = response.getWriter();
} catch (IOException e1) {
e1.printStackTrace();
}
// 上传目录地址
String uploadDir = session.getServletContext().getRealPath("/") + "upload/";
// 如果目录不存在,自动创建文件夹
File dir = new File(uploadDir);
if (!dir.exists()) {
dir.mkdir();
}
try {
for (int i = 0; i < file.length; i++) {
String fileName = FileUtil.uploadImage(imgTempSavePath, file[i]);
out.print("<script type=\"text/javascript\">");
out.print("window.parent.CKEDITOR.tools.callFunction(" + callback + ",'"
+ imgVisitPath + fileName + "','')");
out.print("</script>");
}
} catch (Exception e) {
out.print("<script type=\"text/javascript\">");
out.print("window.parent.CKEDITOR.tools.callFunction(" + callback + ",''," + "'文件上传失败!');");
out.print("</script>");
}
}
}
工具类:
/**
* 文件工具类
* @author intecwh
*
*/
public class FileUtil {
private final static Logger LOG = LoggerFactory.getLogger(FileUtil.class);
/**
* 上传图片工具类,返回图片名
* @return
*/
public static String uploadImage(String tempSavePath, MultipartFile imgFile) throws Exception {
Date date = new Date();
String fileName = ((Long)date.getTime()).toString() + imgSuffix(imgFile.getOriginalFilename());
FileOutputStream fos = null;
try {
String path = createChildPath();
File file = createFile(tempSavePath+path, fileName);
LOG.info("图片名:{}", file.getName());
fos = new FileOutputStream(file);
IOUtils.copy(imgFile.getInputStream(), fos);
LOG.info("图片上传成功");
return path+file.getName();
} catch (IOException ex) {
ex.printStackTrace();
LOG.error("文件创建失败");
throw ex;
} catch (Exception ex) {
ex.printStackTrace();
LOG.info("图片上传失败");
throw ex;
} finally {
if(fos!=null) {
fos.close();
}
}
}
/**
* 生成文件
* @param parentPath
* @param fileName
* @return
* @throws IOException
*/
public static File createFile(String parentPath, String fileName) throws Exception {
File parentFile = new File(parentPath);
if(!parentFile.exists()) {
parentFile.mkdirs();
}
File file = new File(parentPath + fileName);
do {
if(file.exists()) {
fileName = ((Long)new Date().getTime()).toString() + imgSuffix(fileName);
file = new File(parentPath + fileName);
} else {
file.createNewFile();
return file;
}
} while(true);
}
/**
* 生成子路径
* @return
*/
public static String createChildPath() {
String[] strings = {
"1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"};
StringBuffer sb = new StringBuffer();
Integer num = 0;
for(int i=0; i<3; ++i) {
for(int j=0; j<2; ++j) {
num = (int)Math.floor(Math.random()*strings.length);
sb.append(strings[num]);
}
sb.append("/");
}
return sb.toString();
}
/**
* 获取图片的格式,带点,例如:.jpg
* @param imgName
* @return
*/
public static String imgSuffix(String imgName) throws Exception {
if(StringUtils.isEmpty(imgName)) {
LOG.error("图片名为空");
throw new RuntimeException("图片名为空");
}
return imgName.substring(imgName.indexOf("."));
}
}
结果封装类ResultDto:
/**
* 结果封装类
* Created by Administratoron 2018/12/18
**/
public class ResultDto<T> {
private boolean successFlag;
private T data;
public static <T> ResultDto success() {
ResultDto resultDto = new ResultDto();
resultDto.setSuccessFlag(true);
return resultDto;
}
public static <T> ResultDto<T> success(T data) {
ResultDto<T> resultDto = new ResultDto<>();
resultDto.setSuccessFlag(true);
resultDto.setData(data);
return resultDto;
}
public static <T> ResultDto fail() {
ResultDto resultDto = new ResultDto();
resultDto.setSuccessFlag(false);
return resultDto;
}
public static <T> ResultDto<T> fail(T data) {
ResultDto<T> resultDto = new ResultDto<>();
resultDto.setSuccessFlag(false);
resultDto.setData(data);
return resultDto;
}
public boolean isSuccessFlag() {
return successFlag;
}
public void setSuccessFlag(boolean successFlag) {
this.successFlag = successFlag;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
如果图片是上传到本地,可以配置一下静态资源映射,这样,当我们访问指定的URL时,会到指定的本地磁盘中找图片:
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Autowired
private StringToDateConverter stringToDateConverter;
/** 图片临时存储路径 **/
@Value("${img.temp.save.path}")
private String imgTempSavePath;
/** 图片最终存储路径 **/
@Value("${img.fin.save.path}")
private String imgFinSavePath;
/** 图片的访问路径 **/
@Value("${img.visit.path}")
private String imgVisitPath;
/**
* 静态资源映射
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// TODO Auto-generated method stub
registry
.addResourceHandler(imgVisitPath+"**")
.addResourceLocations("file:"+imgTempSavePath+"/")
.addResourceLocations("file:"+imgFinSavePath+"/");
super.addResourceHandlers(registry);
}
}
配置文件:
# 图片的临时存储路径
img.temp.save.path=E:/img/temp/
# 图片的最终保存路径
img.fin.save.path=E:/img/fin/
# 图片的访问路径
img.visit.path=/com/intec/
# 文件的保存路径
file.save.path=E:/file/
二、自定义文件上传插件
在CKeditor的plugins目录下面新建文件夹,文件夹的名字是自定义的插件名,结构如下:
uploadFile中的plugin.js:
CKEDITOR.plugins.add('uploadFile', {
init: function (editor) {
// 防止重复提交Ajax请求
var flag=false;
// 在toolbar中添加上传图片的插件按钮
editor.ui.addButton( 'uploadFile', {
label: '上传文件', // 调用时显示的名称
command: 'uploadFile',
toolbar: 'insert',
icon: this.path + 'icons/uploadFile.png' // 在toolbar中的图标
});
editor.addCommand('uploadFile', {
exec: function(editor) {
// 获取富文本中选中的文本
var text = editor.getSelection().getSelectedText();
if(!isNotEmpty(text)) {
alert("请选择一段文字作为下载链接。");
return;
}
/**
* 页面中要有一个form,向引入的页面中的form中添加一个input:
* <input type="file" id="uploadFile" style="display: none" />
**/
var input = document.createElement( 'input' );
input.setAttribute("type", "file");
input.setAttribute("id", "uploadFile");
input.style.display = 'none';
document.getElementsByTagName("form")[0].prepend(input);
// 上传文件
$("#uploadFile").unbind("change").on('change', function() {
if(flag) {
alert("正在上传文件,请稍后再试");
return;
}
flag = true;
var formData = new FormData();
formData.append("file", $("#uploadFile")[0].files[0]);
$.ajax({
type: 'POST',
url: '/api/common/uploadFile',
data: formData,
cache: false,
processData: false,
contentType: false,
success: function(result) {
if(result.successFlag) {
alert("文件上传成功");
// 将我们选择的文本替换成超链接
var a = editor.document.createElement( 'a' );
// 将返回的文件名拼接到超链接的href中,当我们在页面中点击超链接时可以下载文件
a.setAttribute("href", "/api/common/downloadFile/"+result.data);
a.setText(text);
editor.insertElement(a);
} else {
alert(result.data);
}
},
error: function () {
alert("文件上传失败!");
},
complete: function () {
flag = false;
}
});
});
$("#uploadFile").click();
}
});
// 判断字符串去前后空格后是否不为空字符串
function isNotEmpty(str) {
if(str==null || str=="" || str==undefined) {
return false;
}
// 去前后空格
str = $.trim(str);
if(str=="") {
return false;
}
return true;
}
}
});
然后将我们自定义的文件上传插件添加到config.js中,在config.js中加入代码:
// 添加自定义插件
config.extraPlugins = 'uploadFile';
上传文件和点击超链接下载文件的后台代码:
@RestController
@RequestMapping(value = "/api/common")
public class CommonApi {
/** 文件的保存路径 **/
@Value("${file.save.path}")
private String fileSavePath;
private final static Logger LOG = LoggerFactory.getLogger(CommonApi.class);
/**
* 上传文件
* @param file
* @return
*/
@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public ResultDto uploadFile(@RequestParam("file") MultipartFile file) {
if(file!=null) {
String fileName = file.getOriginalFilename();
// 上传文件,并返回新生成的文件编号
String fileNo = FileUtil.uploadFile(fileSavePath, file);
if(StringUtils.isEmpty(fileNo)) {
LOG.info("文件上传失败");
return ResultDto.fail("文件上传失败");
}
// 将文件编号和文件名保存到数据库中
tranFileInfoService.insert(fileNo, fileName);
LOG.info("文件上传成功,文件编号:", fileNo);
return ResultDto.success(fileNo);
}
return ResultDto.fail("请上传一个文件");
}
/**
* 下载文件
* @param fileNo:文件编号
* @param request
* @param response
*/
@RequestMapping(value = "/downloadFile/{fileNo}")
public void downloadFile(@PathVariable String fileNo, HttpServletRequest request, HttpServletResponse response) {
try {
TranFileInfo tranFileInfo = tranFileInfoService.getByFileNo(fileNo);
if(tranFileInfo==null) {
LOG.info("编号为:{} 的文件不存在", fileNo);
return;
}
response.setContentType("application/octet-stream");
response.setContentType("application/vnd.ms-excel;charset=utf-8");
// 解决下载的文件的文件名出现中文乱码
response.setHeader("Content-disposition", "attachment;filename="+new String(tranFileInfo.getFileName().getBytes("gb2312"), "ISO8859-1" ));
response.flushBuffer();
// 获取文件
File file = new File(fileSavePath + tranFileInfo.getFileNo() + "." + tranFileInfo.getType());
// 将文件下载到本地
DataInputStream in = new DataInputStream(new FileInputStream(file));
//输出流
OutputStream out = response.getOutputStream();
//输出文件
int bytes = 0;
byte[] bufferOut = new byte[1024];
while ((bytes = in.read(bufferOut)) != -1) {
out.write(bufferOut, 0, bytes);
}
LOG.info("编号为:{} 的文件下载成功,文件名:{}", tranFileInfo.getFileNo(), tranFileInfo.getFileName());
out.close();
in.close();
} catch (Exception ex) {
LOG.info("编号为:{} 的文件下载失败", fileNo);
ex.printStackTrace();
}
}
}
上传按钮图片:
富文本样式
选中富文本中的内容,点击下载文件的按钮,会提示我们上传文件
文件上传完成后,会提示我们文件上传成功后上传失败
此时查看源码,就会发现我们选中的文本变成了超链接
点击页面上的超链接会下载文件