【完整靠谱版】结合公司项目,仔细总结自己使用百度编辑器实现FTP上传的完整过程
2016-08-03 17:59
726 查看
说在前面
工作中会遇到很多需要使用富文本编辑器的地方,比如我现在发布这篇文章离不开这个神器,而且现在网上编辑器太多了。记得之前,由于工作需要自己封装过一个编辑器的公共插件,是用ckeditor改版的,目的是要兼容公司所有项目,使用方便。废话不多说,今天写这篇文章,一是总结自己学习复习,二是关于FTP上传官方资料太少,也便于他人少趟坑,我在这里会说的很细很明白,希望亲们以后不要中枪了!关于编辑器的简单部署
去官网下载后,我们需要把下载的编辑器文件夹,摘一部分放到项目中,下载之后的目录,如下图(我这里用的是jsp简化版 1.2.2)![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/13/992c63f11c15aaf6122ee96cdab2a5c5.png)
除了jsp文件夹,其余拷到项目静态资源的目录中,然后 我们来分析jsp文件夹都有哪些东东?
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/13/5c8b27a8a7ff6b19c3fa522aa67ab440.png)
这里,我把那两个jar包带入到项目中,这里我改了名字,方便导入,fileupload那个jar包项目之前就有。如下图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/13/f084909dcc9bc84ac453db9ac012bd94.png)
接下来,就是页面调用了,很简单,首先将编辑器所需要的样式和脚本文件引入:
/**以上省略,这里引入到页面头部**/ <link href="${ctx}/static/umeditor/themes/default/css/umeditor.css" type="text/css" rel="stylesheet"> <script type="text/javascript" charset="utf-8" src="${ctx}/static/umeditor/umeditor.config.js"></script> <script type="text/javascript" charset="utf-8" src="${ctx}/static/umeditor/umeditor.min.js"></script> <script type="text/javascript" src="${ctx}/static/umeditor/lang/zh-cn/zh-cn.js"></script> </head>
接下来,需要在页面调用编辑器对象,官方用的是script标签,我这里用textarea来构造
<div class="controls"> <form:textarea id="content" htmlEscape="true" path="articleData.content" rows="4" maxlength="200" class="input-xxlarge"/> <script type="text/javascript"> //实例化编辑器 var um = UM.getEditor('content'); //注意ID的一致 um.setWidth(700); //设置编辑器宽度 </script> </div>
至此基本的工作已做完,上述相信大部分搞开发的同胞们,都没问题吧!效果图如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/13/d18093348c3daea3c87ff506eb77d5c4.png)
关于编辑器的后台实现
官方下载给的后台处理文件除了必要的jar外有三个文件:(1) Uploader.java 文件
该文件主封装了一个文件上传对象,包括上传后需要返回的参数、状态、URL,除此还有一个上传的处理函数,当然只是普通的文件存储,不符合我们的需求,但是我们可以知道前端需要的一些返回值。
(2) imageUp.jsp 文件
上传图片默认配置后台处理文件,主要调用Upload上传类,完成上传 并把上传结果 以json字符串发往前台,其中包括重要的state、url等参数
(3) getContent.jsp 文件 (和上传没关系,略过)
以上分析过官方给的简单后台处理逻辑,我们不难知道实际上就是需要我们提供一个上传处理函数并返回包含必要参数的JSON串
那好,接下来我们开始写自己的后台上传处理函数了。
第一步 后台控制器处理函数(重要程度:☆☆☆☆☆)
/** * 编辑器上传图片 */ @RequiresPermissions("cms:article:view") @RequestMapping(value={"/upload"}) @ResponseBody() public String upload(HttpServletRequest request,HttpServletResponse response){ //request.getParameter("path"); String[] allowExtName = {".jpg",".png",".gif",".bmp",".jpeg"};//图片格式限制 List<MultipartFile> multipartFiles = getFileSet(request, 1024 * 1024 * 10, allowExtName); //上传的图片大小可以放到配置中读取,这里设置10M Map<String,Object> map = new HashMap<String,Object>(); try { if(multipartFiles.size() > 0){ MultipartFile file = multipartFiles.get(0); InputStream is = file.getInputStream(); String tempFileName = file.getOriginalFilename(); if(is != null&&StringUtils.isNotBlank(tempFileName)){ //生成文件名 String uuid = IdGen.uuid(); //生成的一个随机字符串,用于图片名 String fileName = uuid+tempFileName.substring(tempFileName.indexOf(".")); //生成文件路徑 boolean ftpWaterRs=true; FTPUtils ftpUtils = FTPUtils.getInstance(); SimpleDateFormat sf = new SimpleDateFormat("yyyy/MM/"); String ss = sf.format(new Date()); //以当前时间,生成存放目录,格式/yyyy/MM String storePath = ftpUtils.getSaveFilePath() + ss; //读取配置的存储目录 比如 /upload/image/ //图片加水印 getResourceRootRealPath ; 若图片大小小于logo大小则不加水印 if(file.getSize()>1200){ //这里给图片增加水印功能 String waterName= uuid + "_water"+tempFileName.substring(tempFileName.indexOf(".")); //缓存文件类型转换 CommonsMultipartFile cf= (CommonsMultipartFile)file; DiskFileItem fi = (DiskFileItem)cf.getFileItem(); File tempFile = fi.getStoreLocation(); String waterTempPath = SpringContextHolder.getRootRealPath()+"/"+waterName; String logoPath=SpringContextHolder.getRootRealPath()+"/static/images/shuiyin.png"; //水印图片路径 ImageUtils.markImageByIcon(logoPath, tempFile, waterTempPath, 45); //添加水印 File waterFile = new File(waterTempPath); //上传水印图片 ftpWaterRs = ftpUtils.storeFile(storePath,waterName,new FileInputStream(waterFile)); if(ftpWaterRs){ FileUtils.deleteFile(waterTempPath); is.close(); map.clear(); map.put("state","SUCCESS"); //注意:返回的参数state 成功必须是 SUCCESS,否则需要到image.js中改,失败可以自定义 //map.put("url",ftpUtils.getSiteName().trim()+storePath.trim() + waterName); map.put("url",storePath.trim() + waterName); //url 这里有个坑,绝对完整地址图片不会显示 //我现在返回的是不包含域名的路径 如 /upload/images/2016/08/03/a23ssds6s6d56ds656a6a5652636.jpg //域名部分路径也就是http://static.xx.com/ 需要到前端配置,具体是 在umeditor.config.js 配置参数 imagePath 所谓的图片修正地址喽 return JsonMapper.toJsonString(map); } } //上传源文件 boolean ftpFileRs = ftpUtils.storeFile(storePath, fileName, is); is.close(); if(ftpFileRs){ //这里水印图片上传失败 会采用原图 map.clear(); map.put("state","SUCCESS"); map.put("url",storePath.trim() + fileName); return JsonMapper.toJsonString(map); } } } else{ map.clear(); map.put("state","请检查图片格式或尺寸,图片必须小于10M"); return JsonMapper.toJsonString(map); } } catch (Exception e) { e.printStackTrace(); } map.clear(); map.put("state","上传请求异常"); return JsonMapper.toJsonString(map); }
第二步 处理函数用到上传图片验证函数包含大小和格式(重要程度:☆☆☆)
/** * @descrption 根据HttpServletRequest对象获取MultipartFile集合 * @author zp * @param request * @param maxLength * 文件最大限制 * @param allowExtName * 不允许上传的文件扩展名 * @return MultipartFile集合 */ public static List<MultipartFile> getFileSet(HttpServletRequest request, long maxLength, String[] allowExtName) { MultipartHttpServletRequest multipartRequest = null; try { multipartRequest = (MultipartHttpServletRequest) request; } catch (Exception e) { return new LinkedList<MultipartFile>(); } List<MultipartFile> files = new LinkedList<MultipartFile>(); files = multipartRequest.getFiles("upfile"); //upfile 是编辑器默认的上传图片表单name,在文件umeditor.config.js 可自定义配置参数 imageFieldName // 移除不符合条件的 for (int i = 0; i < files.size(); i++) { if (!validateFile(files.get(i), maxLength, allowExtName)) { files.remove(files.get(i)); if (files.size() == 0) { return files; } } } return files; } /** * @descrption 验证文件格式,这里主要验证后缀名 * @author zp * @param file * MultipartFile对象 * @param maxLength * 文件最大限制 * @param allowExtName * 不允许上传的文件扩展名 * @return 文件格式是否合法 */ private static boolean validateFile(MultipartFile file, long maxLength, String[] allowExtName) { if (file.getSize() < 0 || file.getSize() > maxLength) return false; String filename = file.getOriginalFilename(); // 处理不选择文件点击上传时,也会有MultipartFile对象,在此进行过滤 if (filename == "") { return false; } String extName = filename.substring(filename.lastIndexOf(".")) .toLowerCase(); if (allowExtName == null || allowExtName.length == 0 || Arrays.binarySearch(allowExtName, extName) != -1) { return true; } else { return false; } }
第三步 FTP上传处理类,绝对福利..好多人想要哦 0.0(重要程度:☆☆☆[b]☆[/b])
package com.xx.utils; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply; import com.xx.Global; /** * FTP服务器工具类 */ public class FTPUtils { private static FTPUtils ftpUtils; private FTPClient ftpClient; //private FTPFile ftpFile; private String port; // 服务器端口 private String username; // 用户登录名 private String password; // 用户登录密码 private String serverName; // 服务名 private int localPasv;//开启本地被动模式 private String siteName; // 站点域名 private String saveFilePath;//存储路径 private InputStream is; // 文件下载输入流 /** * 私有构造方法 */ private FTPUtils() { initConfig(); if (null == ftpClient) { ftpClient = new FTPClient(); } } /** * 获取FTPUtils对象实例 * @return * FTPUtils对象实例 */ public synchronized static FTPUtils getInstance () { if (null == ftpUtils) { ftpUtils = new FTPUtils(); } return ftpUtils; } /** * 初始化FTP服务器连接属性 */ // public void initConfig () { // // 构造Properties对象 // Properties properties = new Properties(); // // // 定义配置文件输入流 // InputStream is = null; // try { // // 获取配置文件输入流 // is = FTPUtils.class.getResourceAsStream("/ftp.properties"); // // 加载配置文件 // properties.load(is); // // 读取配置文件 // port = (String) properties.get("port"); // 设置端口 // username = (String) properties.get("username1"); // 设置用户名 // password = (String) properties.get("password1"); // 设置密码 // serverName = (String) properties.get("serverName"); // 服务名 // localPasv = Integer.valueOf(String.valueOf(properties.get("localPasv"))); // } catch (IOException e) { // e.printStackTrace(); // } finally { // // 判断输入流是否为空 // if (null != is) { // try { // // 关闭输入流 // is.close(); // } catch (IOException e) { // e.printStackTrace(); // } // } // } // } public void initConfig () { serverName = Global.getConfig("ftp.serverName"); // SystemConfig.getInstance().getApplication().get("ftp.serverName"); port = Global.getConfig("ftp.port"); // SystemConfig.getInstance().getApplication().get("ftp.port"); username = Global.getConfig("ftp.username1"); // SystemConfig.getInstance().getApplication().get("ftp.username1"); password =Global.getConfig("ftp.password1"); // portSystemConfig.getInstance().getApplication().get("ftp.password1"); localPasv = Integer.valueOf(Global.getConfig("ftp.localPasv")); // Integer.valueOf(SystemConfig.getInstance().getApplication().get("ftp.localPasv")); siteName = Global.getConfig("ftp.readPath"); //读取配置 访问路径 saveFilePath = Global.getConfig("ftp.upLoadPath"); //读取配置 上传路径 } /** * 连接(配置通用连接属性)至服务器 * * @param serverName * 服务器名称 * @param remotePath * 当前访问目录 * @return * <b>true</b>:连接成功 * <br/> * <b>false</b>:连接失败 */ public boolean connectToTheServer (String remotePath) { // 定义返回值 boolean result = false; try { // 连接至服务器,端口默认为21时,可直接通过URL连接 ftpClient.connect(serverName, Integer.parseInt(port)); // 登录服务器 ftpClient.login(username, password); // 判断返回码是否合法 if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) { // 不合法时断开连接 ftpClient.disconnect(); // 结束程序 return result; } if(localPasv==1) ftpClient.enterLocalPassiveMode(); // 设置文件操作目录 result = createDirAndToDir(remotePath); System.out.println("result===="+result); // 设置文件类型,二进制 result = ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); // 设置缓冲区大小 ftpClient.setBufferSize(3072); // 设置字符编码 ftpClient.setControlEncoding("UTF-8"); } catch (IOException e) { e.printStackTrace(); } return result; } /** * 上传文件至FTP服务器 * * @param serverName * 服务器名称 * @param storePath * 上传文件存储路径 * @param fileName * 上传文件存储名称 * @param is * 上传文件输入流 * @return * <b>true</b>:上传成功 * <br/> * <b>false</b>:上传失败 */ public boolean storeFile (String storePath, String fileName, InputStream is) { boolean result = false; try { // 连接至服务器 result = connectToTheServer(storePath); // 判断服务器是否连接成功 if (result) { // 上传文件 result = ftpClient.storeFile(fileName, is); } // 关闭输入流 is.close(); } catch (IOException e) { e.printStackTrace(); } finally { // 判断输入流是否存在 if (null != is) { try { // 关闭输入流 is.close(); } catch (IOException e) { e.printStackTrace(); } } // 登出服务器并断开连接 ftpUtils.logout(); } return result; } /** * 下载FTP服务器文件至本地<br/> * 操作完成后需调用logout方法与服务器断开连接 * 服务器名称 * @param remotePath * 下载文件存储路径 * @param fileName * 下载文件存储名称 * @return * <b>InputStream</b>:文件输入流 */ public InputStream retrieveFile (String remotePath, String fileName) { try { boolean result = false; // 连接至服务器 result = connectToTheServer(remotePath); // 判断服务器是否连接成功 if (result) { // 获取文件输入流 is = ftpClient.retrieveFileStream(fileName); } } catch (IOException e) { e.printStackTrace(); } return is; } /** * 删除FTP服务器文件 * * @param serverName * 服务器名称 * @param remotePath * 当前访问目录 * @param fileName * 文件存储名称 * @return * <b>true</b>:删除成功 * <br/> * <b>false</b>:删除失败 */ public boolean deleteFile (String serverName, String remotePath, String fileName) { boolean result = false; // 连接至服务器 result = connectToTheServer(remotePath); // 判断服务器是否连接成功 if (result) { try { // 删除文件 result = ftpClient.deleteFile(fileName); } catch (IOException e) { e.printStackTrace(); } finally { // 登出服务器并断开连接 ftpUtils.logout(); } } return result; } /** * 创建目录 * * @param remotePath * 目录储路径 * @return * <b>true</b>:创建成功 * <br/> * <b>false</b>:创建失败 */ public boolean createDirAndToDir (String remotePath) { boolean result = false; try { // 连接至服务器 //result = ftpClient.changeWorkingDirectory(remotePath); String [] dirs = remotePath.split("/"); if(dirs!=null){ String tempDir = ""; for(String dir : dirs){ tempDir += dir +"/"; result = ftpClient.changeWorkingDirectory(tempDir); if(!result){ result = ftpClient.makeDirectory(dir); ftpClient.changeWorkingDirectory(dir); } } } } catch (IOException e) { e.printStackTrace(); return false; } return true; } /** * 检测FTP服务器文件是否存在 * 服务器名称 * @param remotePath * 检测文件存储路径 * @param fileName * 检测文件存储名称 * @return * <b>true</b>:文件存在 * <br/> * <b>false</b>:文件不存在 */ public boolean checkFile (String remotePath, String fileName) { boolean result = false; try { // 连接至服务器 result = connectToTheServer(remotePath); // 判断服务器是否连接成功 if (result) { // 默认文件不存在 result = false; // 获取文件操作目录下所有文件名称 String[] remoteNames = ftpClient.listNames(); // 循环比对文件名称,判断是否含有当前要下载的文件名 for (String remoteName: remoteNames) { if (fileName.equals(remoteName)) { result = true; } } } } catch (IOException e) { e.printStackTrace(); } finally { // 登出服务器并断开连接 ftpUtils.logout(); } return result; } /** * 登出服务器并断开连接 * * @param ftp * FTPClient对象实例 * @return * <b>true</b>:操作成功 * <br/> * <b>false</b>:操作失败 */ public boolean logout () { boolean result = false; if (null != is) { try { // 关闭输入流 is.close(); } catch (IOException e) { e.printStackTrace(); } } if (null != ftpClient) { try { // 登出服务器 result = ftpClient.logout(); } catch (IOException e) { e.printStackTrace(); } finally { // 判断连接是否存在 if (ftpClient.isConnected()) { try { // 断开连接 ftpClient.disconnect(); } catch (IOException e) { e.printStackTrace(); } } } } return result; } public String getSiteName() { return siteName; } public String getSaveFilePath() { return saveFilePath; } }
第四步 用到的副类,真正做到任君品尝 !!(重要程度:☆☆)
(1)IDGen工具类
/** * 随机ID工具类 */ package com.xx.utils; import java.io.Serializable; import java.security.SecureRandom; import java.text.DecimalFormat; import java.util.Date; import java.util.UUID; import org.apache.shiro.session.Session; import org.apache.shiro.session.mgt.eis.SessionIdGenerator; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; /** * 封装各种生成唯一性ID算法的工具类. * @author ThinkGem * @version 2013-01-15 */ @Service @Lazy(false) public class IdGen implements SessionIdGenerator { private static SecureRandom random = new SecureRandom(); private static int num; /** * 封装JDK自带的UUID, 通过Random数字生成, 中间无-分割. */ public static String uuid() { return UUID.randomUUID().toString().replaceAll("-", ""); } /** * 生成投资编号 * @return */ public static String investNo(){ String date = DateUtils.formatDateToStr("yyyyMMddHHmmss",new Date()); if(num>999999){ num = 0; } String numStr = new DecimalFormat("000000").format(num++); return date.substring(2)+ numStr; } /** * 使用SecureRandom随机生成Long. */ public static long randomLong() { return Math.abs(random.nextLong()); } @Override public Serializable generateId(Session session) { return IdGen.uuid(); } public static String getRandomName(int k){ String chars = "abcdefghijklmnopqrstuvwxyz0123456789"; StringBuilder sb = new StringBuilder(); for (int i = 0; i < k; i++) { sb.append(chars.charAt((int)(Math.random() * 36))); } return sb.toString(); } }
(2)ImageUtil工具类
package com.xx.utils; import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Image; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 图片处理类 * @author xx */ public class ImageUtils { private final static Logger logger = LoggerFactory.getLogger(ImageUtils.class); // 水印透明度 private static float alpha = 0.5f; // 水印横向位置 private static int positionWidth = 150; // 水印纵向位置 private static int positionHeight = 300; // 水印文字字体 private static Font font = new Font("宋体", Font.BOLD, 30); // 水印文字颜色 private static Color color = Color.red; /** * 给图片添加图片水印 * @param iconPath 水印图片路径 * @param file 源文件 * @param targerPath 目标图片路径 * @param degree 水印图片旋转角度 */ public static void markImageByIcon(String iconPath, File file, String targerPath, Integer degree) { OutputStream os = null; try { logger.info("水印图片路径:{}", iconPath); logger.info("源文件:{}", file.getAbsolutePath()); logger.info("目标图片路径:{}", targerPath); Image srcImg = ImageIO.read(file); BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null), srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB); // 得到画笔对象 Graphics2D g = buffImg.createGraphics(); // 设置对线段的锯齿状边缘处理 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.drawImage(srcImg.getScaledInstance(srcImg.getWidth(null), srcImg .getHeight(null), Image.SCALE_SMOOTH), 0, 0, null); if (null != degree) { // 设置水印旋转 g.rotate(Math.toRadians(degree), (double) buffImg.getWidth() / 2, (double) buffImg .getHeight() / 2); } // 水印图象的路径 水印一般为gif或者png的,这样可设置透明度 ImageIcon imgIcon = new ImageIcon(iconPath); // 得到Image对象。 Image img = imgIcon.getImage(); float alpha = 0.5f; // 透明度 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, alpha)); // 表示水印图片的位置 相对于中心店的宽高以及水印图片宽高(img,x,y,width,height,obnull) g.drawImage(img, buffImg.getWidth() / 6,buffImg.getHeight() / 3, buffImg.getWidth() / 2,buffImg.getHeight() / 4, null); g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); g.dispose(); os = new FileOutputStream(targerPath); // 生成图片 ImageIO.write(buffImg, "JPG", os); logger.info("图片完成添加水印"); } catch (Exception e) { e.printStackTrace(); logger.error("图片完成添加水印error:{}", e.getMessage()); } finally { try { if (null != os) os.close(); } catch (Exception e) { e.printStackTrace(); } } } /** * 给图片添加水印文字 * @param logoText 水印文字 * @param srcImgPath 原图片路径 * @param targerPath 目标图片路径 * @param degree 旋转角度 */ public static void markImageByText(String logoText, String srcImgPath, String targerPath, Integer degree) { InputStream is = null; OutputStream os = null; try { // 1、源图片 Image srcImg = ImageIO.read(new File(srcImgPath)); BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null),srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB); // 2、得到画笔对象 Graphics2D g = buffImg.createGraphics(); // 3、设置对线段的锯齿状边缘处理 g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.drawImage(srcImg.getScaledInstance(srcImg.getWidth(null), srcImg.getHeight(null), Image.SCALE_SMOOTH), 0, 0, null); // 4、设置水印旋转 if (null != degree) { g.rotate(Math.toRadians(degree),(double) buffImg.getWidth() / 2, (double) buffImg.getHeight() / 2); } // 5、设置水印文字颜色 g.setColor(color); // 6、设置水印文字Font g.setFont(font); // 7、设置水印文字透明度 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,alpha)); // 8、第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y) g.drawString(logoText, positionWidth, positionHeight); // 9、释放资源 g.dispose(); // 10、生成图片 os = new FileOutputStream(targerPath); ImageIO.write(buffImg, "JPG", os); logger.info("图片完成添加水印文字"); } catch (Exception e) { e.printStackTrace(); } finally { try { if (null != is) is.close(); } catch (Exception e) { e.printStackTrace(); } try { if (null != os) os.close(); } catch (Exception e) { e.printStackTrace(); } } } /** * 判断文件是不是图片 * @param file * @return * @author guogf */ public static boolean isImage(File file) { boolean flag = false; try { Image is = ImageIO.read(file); if(null != is) { flag = true; } } catch (Exception e) { e.printStackTrace(); } return flag; } }
关于编辑器的前台配置
到此后台处理函数已完整实现,现在需要将后台返回的json串回调到前端编辑器来处理,写入上传容器框以及编辑器文章当中。首先去找到umeditor.config.js 找到如下并修改:
//图片上传配置区 ,imageUrl:ctx+"/cms/article/upload" //图片上传提交地址 很重要!上传提交地址,这里配置成我刚才写的那个控制器函数 路径很重要 ctx获取的是当前域名 ,imagePath:"http://static.xx.com/" //图片修正地址,对应刚才我提到的域名配置的地方 必须配置!! ,imageFieldName:"upfile" //图片数据的key,若此处修改,需要在后台对应文件修改对应参数 对应刚才提到的上传图片的表单name 默认即可
配置好之后,后来调试发现 返回的json 串包含在pre标签里,编辑器脚本解析不了,报错,所以,这里还需要修改编辑器目录 dialogs\image\image.js文件
uploadComplete: function(r){ debugger; var me = this; try{ var json = eval('('+$(r).html()+')'); //这里需要把返回的字符串转化成对象 pre对象,然后获取里面json串 Base.callback(me.editor, me.dialog, json.url, json.state); }catch (e){ var lang = me.editor.getLang('image'); Base.callback(me.editor, me.dialog, '', (lang && lang.uploadError) || 'Error!'); } },
好了,到这里基本完事了,我们看下最终效果吧!
开始上传效果图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/13/bef2f89a4b32eec6cddd57fc32eda3de.png)
拖曳或者上传效果图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/13/d24c3e542547872f6bf296f6f093ea9c.png)
编辑器效果图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/13/818dbe2b789f40ba3817202b828bceac.png)
文章预览效果图:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/13/2a133b4f5541588598e71013445a45f4.png)
说在后面
这篇博文写了挺长时间,手都酸了...之前有部分分享总是被移除首页,所以,在格式排版上花很长时间..如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】按钮。
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【关注我】。
如果,想给予我更多的鼓励,求打赏
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/13/acfb15587b3896e8dafbd0d9518998c6.jpg)
![](https://oscdn.geek-share.com/Uploads/Images/Content/202010/13/1818b91d88b22ed3ffff572d8ac16827.png)
欢迎资助我持续写作,金额随意,欢迎来赏!
因为,我的写作热情也离不开您的肯定支持。
感谢您的阅读,如果您对我的博客所讲述的内容有兴趣,请继续关注我的后续博客 。
另外,需要声明:原创博客请在转载时保留原文链接或者在文章开头加上本人博客地址(http://www.cnblogs.com/sybboy),如发现错误,欢迎批评指正。
相关文章推荐
- [项目过程中所遇到的各种问题记录]编辑器篇——使用FCKeditor生成静态分页HTML
- [项目过程中所遇到的各种问题记录]编辑器篇——使用FCKeditor生成静态分页HTML
- AndroidPn项目实现推送的使用过程
- 使用UML建立的完整的系统用例的实现过程
- 在Java Web项目里实现IOC(不使用框架,自己通过代码实现)
- 项目开发过程中自己的总结
- EclipsePlug-in使用TextEditor开发自己的编辑器,实现关键字高亮和代码提示.
- CKEditor使用js结合CKFinder实现上传,解决项目路径问题
- 使用mssql2008新特性(存储过程参数类型使用"用户自定义表"来实现批量DML更新多表)解决项目里遇到的性能问题
- JAVA_WEB项目(结合Servlet+jsp+ckEditor编辑器+jquery easyui技术)实现新闻发布管理系统第一篇:前期环境准备
- [项目过程中所遇到的各种问题记录]编辑器篇——FCKeditor相关知识及各种常见使用问题
- 很多人想要的Jquery 加载Loading效果,可以加到自己的项目中,结合Ajax使用
- 微软、谷歌、百度等公司经典面试100题[第1-60题]——自己的实现
- 在项目中使用最新的ckeditor4.3.1的全过程+增加自己的上传本地图片按钮及将上传图片返回、保存
- [项目总结]在ios中使用soundtouch库实现变声 推荐
- 由于Python本身自带的界面库功能并不强大,我们使用Python+wxPython作为界面开发平台,在公司新的项目中进行界面开发。开发过程使用Eclipse+PyDev 作为集成开发环境。产品发布时使用Py2exe进行打包。如今,在我的团队中,Pytho
- TortoiseSVN 结合项目实践使用总结
- AndroidPn项目实现推送的使用过程
- 微软、谷歌、百度等公司经典面试100题[第1-60题]——自己的实现[转]
- 项目实现过程中遇到的问题记录(二)------------在Thread中使用CallBack并没有调用CallBack的返回