解决:百度编辑器Ueditor跨域上传图片
问题:百度编辑器上传图片到本项目的时候,没有问题,一旦跨域上传图片的时候就会导致图片上传错误,原因是因为百度编辑器使用的编辑区域是IFrame,而父窗口和主窗口的数据不可跨域调用.
解决方案:将百度编辑器的图片数据提交到本项目,获取到图片的字节文件,接着使用远程方法调用将字节数据发送到图片项目存储到硬盘,存储成功之后,将图片的引用URL及其他信息以RMI的返回值返回,在本项目中将接收的上传成功的数据翻译到前端
所用技术:Ueditor、spring3.0+springMVC、spring3.0+hessian3.0
思想:
具体代码:
1、Ueditor demo.html
<!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8"> <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> <title>ueditor demo</title> </head> <body> <!-- 加载编辑器的容器 --> <script id="UContainer" name="content" type="text/plain" style="margin-top: 300px"> 这里写你的初始化内容 </script> <!-- 配置文件 --> <script type="text/javascript" src="ueditor.config.js"></script> <!-- 编辑器源码文件 --> <script type="text/javascript" src="ueditor.all.js"></script> <!-- 实例化编辑器 --> <script type="text/javascript"> //test************windows var uploadImageUrl = 'http://127.0.0.1/ueditor/upload'; UE.Editor.prototype._bkGetActionUrl = UE.Editor.prototype.getActionUrl; UE.Editor.prototype.getActionUrl = function (action) { // if (action == 'uploadimage' || action == 'uploadscrawl' || action == 'uploadimage') { if (action == 'uploadimage') { return uploadImageUrl; } else if (action == 'uploadvideo') { return 'http://a.b.com/video.php'; } else { return this._bkGetActionUrl.call(this, action); } } var toolbarsItems = [ [ 'anchor', //锚点 'undo', //撤销 'redo', //重做 'bold', //加粗 'indent', //首行缩进 'snapscreen', //截图 'italic', //斜体 'underline', //下划线 'strikethrough', //删除线 'subscript', //下标 'fontborder', //字符边框 'superscript', //上标 'formatmatch', //格式刷 //'source', //源代码 'blockquote', //引用 'pasteplain', //纯文本粘贴模式 'selectall', //全选 //'print', //打印 'preview', //预览 'horizontal', //分隔线 'removeformat', //清除格式 'time', //时间 'date', //日期 'unlink', //取消链接 'insertrow', //前插入行 'insertcol', //前插入列 'mergeright', //右合并单元格 'mergedown', //下合并单元格 'deleterow', //删除行 'deletecol', //删除列 'splittorows', //拆分成行 'splittocols', //拆分成列 'splittocells', //完全拆分单元格 'deletecaption', //删除表格标题 'inserttitle', //插入标题 'mergecells', //合并多个单元格 'deletetable', //删除表格 'cleardoc', //清空文档 'insertparagraphbeforetable', //"表格前插入行" //'insertcode', //代码语言 'fontfamily', //字体 'fontsize', //字号 'paragraph', //段落格式 'simpleupload', //单图上传 'insertimage', //多图上传 'edittable', //表格属性 'edittd', //单元格属性 'link', //超链接 'emotion', //表情 'spechars', //特殊字符 'searchreplace', //查询替换 'map', //Baidu地图 //'gmap', //Google地图 //'insertvideo', //视频 'help', //帮助 'justifyleft', //居左对齐 'justifyright', //居右对齐 'justifycenter', //居中对齐 'justifyjustify', //两端对齐 'forecolor', //字体颜色 'backcolor', //背景色 'insertorderedlist', //有序列表 'insertunorderedlist', //无序列表 'fullscreen', //全屏 'directionalityltr', //从左向右输入 'directionalityrtl', //从右向左输入 'rowspacingtop', //段前距 'rowspacingbottom', //段后距 'pagebreak', //分页 //'insertframe', //插入Iframe 'imagenone', //默认 'imageleft', //左浮动 'imageright', //右浮动 'attachment', //附件 'imagecenter', //居中 'wordimage', //图片转存 'lineheight', //行间距 'edittip ', //编辑提示 'customstyle', //自定义标题 'autotypeset', //自动排版 //'webapp', //百度应用 'touppercase', //字母大写 'tolowercase', //字母小写 'background', //背景 'template', //模板 //'scrawl', //涂鸦 //'music', //音乐 'inserttable', //插入表格 //'drafts', // 从草稿箱加载 'charts', // 图表 ] ]; var ue = UE.getEditor('UContainer', { toolbars: toolbarsItems, autoHeightEnabled: true, autoFloatEnabled: true }); </script> </body> </html>
2、common server
@RequestMapping(value = "ueditor/upload", method = RequestMethod.POST) @ResponseBody public Map<String, Object> upload(HttpServletRequest request, HttpServletResponse response) { try { // String uploadDomain = "http://127.0.0.1:8083";//本地测试 Map<String, Object> result = new HashMap<>(); MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) request; MultipartFile multipartFile = multipartHttpServletRequest.getFile("upfile"); Long startTime = System.currentTimeMillis(); String url = uploadDomain + "/hessian/hessianFileUploadImpl"; HessianFileUpload service = (HessianFileUpload) factory.create(HessianFileUpload.class, url); // Map<String, Object> map = service.uploadForStream(multipartHttpServletRequest.getInputStream(),multipartFile.getOriginalFilename(), multipartFile.getSize()); // Map<String, Object> map = service.uploadForSpring(multipartFile); byte[] data = multipartFile.getBytes(); if (data != null && data.length > 5242880 || data == null) {//上限5M 5242880 result.put("state", "文件过大,上传失败,上文大小上限5MB"); return result; } System.err.println("文件大小=" + (data.length)); Map<String, Object> map = service.uploadByBytes(data, multipartFile.getOriginalFilename(), multipartFile.getSize()); System.err.println("duration=" + (System.currentTimeMillis() - startTime)); return map; } catch (Exception e) { e.printStackTrace(); } return null; }
3、Hessian接口
public interface HessianFileUpload { /** * 按字节上传文件 * @return */ Map<String, Object> uploadByBytes(byte[] bytes,String filename, Long available); }
3、hessian实现
/** * 按字节上传, * * @param bytes * @return */ @Override public Map<String, Object> uploadByBytes(byte[] bytes, String oldFilename, Long available) { //test***********************windows本地测试 //download String domain = "http://127.0.0.1:8083/"; String realPathDown = "upload/"; //upload String realPathUpload = "D:\\Program Files (x86)\\JetBrains\\IDEA_WORKSPACE\\QyImage\\src\\main\\webapp\\upload"; //test*******************END // BufferedInputStream bis = null; BufferedOutputStream bos = null; Map<String, Object> jsonObject = new HashMap<>(); try { //获取客户端传递的InputStream // bis = new BufferedInputStream(inputStream); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMdd"); String dateDir = simpleDateFormat.format(new Date()); //上传的路径名***************************** String uploadPath = realPathUpload + File.separator + dateDir; logger.info("uploadPath=" + uploadPath); File filey = new File(uploadPath); if (!filey.exists()) { filey.mkdirs(); } //获取后缀,仅限于图片格式 //[".png", ".jpg", ".jpeg", ".gif", ".bmp"] List<String> limitsuffixList = Arrays.asList(".png", ".jpg", ".jpeg", ".gif", ".bmp"); String suffixName = oldFilename.substring(oldFilename.lastIndexOf("."), oldFilename.length()); if (!limitsuffixList.contains(suffixName)) { jsonObject.put("state", "文件格式不合法,支持的文件类型[\".png\", \".jpg\", \".jpeg\", \".gif\", \".bmp\"]"); return jsonObject;//文件后缀名不合法,上传失败 } //上传的文件名 String filename = UUID.randomUUID() + new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date()) + suffixName; logger.info("filename=" + filename); //文件名不能大于5M if (available > 5242880) { jsonObject.put("state", "文件过大,上传失败"); return jsonObject;//返回上传失败 } String saveFilename = uploadPath + File.separator + filename; //创建文件输出流 bos = new BufferedOutputStream(new FileOutputStream(new File(saveFilename))); // byte[] buffer = new byte[8192]; // int r = bis.read(buffer, 0, buffer.length); // while (r > 0) { // bos.write(buffer, 0, r); // r = bis.read(buffer, 0, buffer.length); // } bos.write(bytes); String imgAccessUrl = domain + realPathDown + File.separator + dateDir + "/" + filename; jsonObject.put("state", "SUCCESS"); jsonObject.put("url", imgAccessUrl);//图片的展示路径 jsonObject.put("title", oldFilename);//图片的名称 jsonObject.put("original", oldFilename); // response.getWriter().write(jsonObject.toString()); // response.setHeader("referer","http://127.0.0.1/"); logger.info(jsonObject.toString()); logger.info("-------upload success!-------------"); return jsonObject; } catch (IOException e) { throw new RuntimeException(e); } finally { if (bos != null) { try { bos.close(); } catch (IOException e) { throw new RuntimeException(e); } } // if (bis != null) { // try { // bis.close(); // } catch (IOException e) { // throw new RuntimeException(e); // } // } } }
4、hessian配置
服务端配置:
web.xml
<!-- hessian 配置 默认会加载hessian-servlet.xml--> <servlet> <servlet-name>hessian</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>hessian</servlet-name> <url-pattern>/hessian/*</url-pattern> </servlet-mapping> <!-- hessian 配置 -->
hessian-servlet.xml
<!-- Hessian访问路径 含权限认证 --> <bean name="/hessianFileUploadImpl" class="com.*.HessianServerProxyExporter"> <property name="service" ref="hessianFileUploadImpl"/> <property name="serviceInterface"> <value> com.yizhilu.os.image.framework.hessian.service.HessianFileUpload </value> </property> </bean>
hessian客户端配置
<!--Ueditor上传图片--> <bean id="hessianFileUpload" class="org.springframework.remoting.caucho.HessianProxyFactoryBean"> <property name="serviceInterface" value="com.*.framework.hessian.service.HessianFileUpload"></property> <property name="serviceUrl"> <value>${fileUploadPath}/hessian/hessianFileUploadImpl</value> </property> <property name="readTimeout"> <value>100000</value> </property> <property name="proxyFactory"> <bean class="com.*.hessian.client.HessianClientProxyFactory" /> </property> <property name="chunkedPost" value="false" /> </bean>