Ueditor 跨域的问题研究

一、背景

这段时间在做CMS毕业设计项目,项目是nodejs后台,angular+require前台
前后端完全分离,采用ajax来获取数据渲染到前台上,所以前端不用任何后台语言,纯html/css/js,我将前端放在了80端口,后端放在3008端口,实际上属于两个完全不同域名。

二、问题

首先是官方没有给nodejs的版本、然后就是这篇文章的主要问题跨域。

三、解决方案

UE官方给的源码都是前后端在一起,我下载了一个PHP版本的,文件结构如下:

其中PHP文件夹是服务端代码,因为我用的node,所以走你~删之~~
其余的我们放入前端相关地方,然后引入之即可,需要引入的文件有三

  1. ueditor.all.(min.)js 主文件不用说
  2. ueditor.config.js 配置文件
  3. third-party/zeroclipboard/ZeroClipboard.min.js
  4. lang下的语言文件

接着,要配置UE的Home,serverUrl,我直接在ueditor.config.js 用绝对路径写死了 然后就可以开心愉快的在页面里使用啦

但是,图片上传呢,服务端呢,翻了官网插件,哎呦,找到一个ue for nodejs果断用之,翻阅其源码,就是处理了一下文件的保存,然后通知前端是否保存成功之类的事情。

var ueditor = require("./ueditor");//注意这里的‘./’ 因为我改了他的代码,所以直接把他的lib/index.js拷出来做为自己的文件用了原版只要直接require("ueditor")就好了(当然前提是你是通过npm install ueditor安装的)
    app.use("/ue",ueditor(path.join(__dirname,'public/upload/'),function(req,res,next) {
        // ueditor 客户发起上传图片请求

        if (req.query.action === 'uploadimage') {

            // 这里你可以获得上传图片的信息
            var foo = req.ueditor;
            // console.log(foo.filename); // exp.png
            // console.log(foo.encoding); // 7bit
            // console.log(foo.mimetype); // image/png

            // 下面填写你要把图片保存到的路径 ( 以 path.join(__dirname,'public') 作为根路径)
            var img_url = req.session.userName;
            res.ue_up(img_url); //你只要输入要保存的地址 。保存操作交给ueditor来做
        }
        // 客户端发起图片列表请求
        else if (req.query.action === 'listimage') {
            var dir_url = req.session.userName; // 插件作者:要展示给客户端的文件夹路径 笔者:这里我用了用户的用户名作为文件夹名字,请读者自行改之
            res.ue_list(dir_url) // 客户端会列出 dir_url 目录下的所有图片
        }
        // 客户端发起其它请求
        else {

            res.setHeader('Content-Type','application/json');
            // 这里填写 ueditor.config.json 这个文件的路径
            res.jsonp(require('./ueditor.config.json'));
        }
    }));

这是后台的服务端,小插曲,UE有两个配置文件,一个是前端的,还有后端的配置文件所以后端,我们只需要用jsonp把下图中的config.json暴露出来就可以,这个文件在 UE官方源码的后台代码文件夹中,这里就是PHP文件夹

这里有个坑,Json标准是不支持注释的,所以用node去解析的时候会出现问题,没办法,我只好把注释全删了(当然做了个备份)

搞定这些之后,现在前端不上传图片就不会报错了,但是人类的欲望是无尽的,我们又怎么能停步于此呢,我们要上传图片!!!不管是单张的(比较坑),还是多张的(非常坑)。
首先讲一下为什么这两个区分开来,我们来看官方的这段话,这段话原地址请点这儿

坑爹有木有,为了兼容低版本浏览器,单图提交用了iframe,而iframe不支持跨域读取内容,完了,我们的欲望要得不到满足了,(┬_┬)↘ 跌,但是官方说要发挥想象力,网上就有人说了,b域名的ue,上传图片到a域名,a域名保存图片成功后,重定向到b域名,在给个参数,b域名后台做处理后在返回就好了。 坑爹,可是我的项目前端没有后台呀!!!那怎么办,然后我就发挥想象力,想象力你懂得!a域名把消息封装成参数,然后重定向到静态页面,静态页面通过js在body onload的时候把消息写到页面上去,就除了如下两个代码

a域名后台代码:

res.ue_up = function(img_url) {
          var tmpdir = path.join(os.tmpdir(),path.basename(filename));
          var name = sNowflake.nextId() + path.extname(tmpdir);
          var dest = path.join(static_url,img_url,name);
          var writeStream = fs.createWriteStream(tmpdir);
          file.pipe(writeStream);
          writeStream.on("close",function() {
            fse.move(tmpdir,dest,function(err) {
              if (err) throw err;
              var obj = {
                'url': host + "upload/" + path.join(img_url,name).replace(/\\/g,'/'),//注意,这里的host是后台服务器地址,因为上传的文件存到a域名下了,所以这里地址也改了。
                'title': req.body.pictitle,'original': filename,'state': 'SUCCESS'
              }

              res.redirect(webAddress + "ue.html?obj=" + encodeURIComponent(JSON.stringify(obj)));//我改了这个地方,将obj封装了之后作为参数重定向到webAddress也就是前端地址的ue.html页面上去
            });
          })
        };

上边这些代码在ueditor for node 的那个lib/index.js里,也就是我的ueditor.js里,

b域名 ue.html:

<html>
<head>
<Meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
<script type="text/javascript"> //获取参数的方法,网上找的 function getUrlParam(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象 var r = window.location.search.substr(1).match(reg); //匹配目标参数 if (r != null) return unescape(r[2]); return null; //返回参数值 } //写参数到页面注意要在onload时调用 var getdata=function() { document.getElementsByTagName('body')[0].innerHTML=getUrlParam('obj'); } </script>
</head>
<body onload="getdata();">

</body>
</html>

这样就完成了单图片上床囧rz=З 传的功能

让后我们来说说多图 Orz

多图上传的原理官方没有解释,我来解释,多图上传通过弹出一个dialogs来实现各种操作,相关文件都在dialogs里,查看dialogs/image/image.html我们发现上传用了webupload,而webupload是通过自己构建ajax来实现图片上传的,唯一有个问题,就是关于跨域session/cookie的问题,UE和webupload都没有说到,要在image.html文件所引入的image.js文件的365行左右初始化webupload配置的时候加上withCredentials:true,参数如下图 否则a域名的后台就得不到session了
当然这里有个小插曲,ajax的跨域需要后台headers配合,下边是我的配置

app.use('/',next) {
    res.header("Access-Control-Allow-Origin",config.cros==="*"?req.headers.origin:config.cros);
    res.header('Access-Control-Allow-Methods','PUT,GET,POST,DELETE,OPTIONS');
    res.header("Access-Control-Allow-Headers","X-Requested-With,x_requested_with");
    res.header("Access-Control-Allow-Credentials","true");//跨域session
    if(req.method=="OPTIONS") res.sendStatus(200);/*让options请求快速返回*/
    else  next();
});

上边为什么在method==options的时候要返回200,详情可以了解 CORS preflight
行了,接下来可以愉快的多图上传了,

什么鬼,跨域访问不允许重定向,我**,单图要重定向,多图ajax不能重定向,算了,只能在后台判断一下是不是ajax,

if (req.xhr||req.headers['x_requested_with']==='XMLHttpRequest') {
                res.jsonp(obj);//如果是ajax则直接jsonp
              } else {
                res.redirect(webAddress + "ue.html?obj=" + encodeURIComponent(JSON.stringify(obj)));//如果是表单提交,也就是单图的iframe提交,则重定向
              }

只此,UE的单图和多图上传在前后端完全分离的跨域情况下完全解决,这是我的方案,在nodejs下,同理可以推广到其他后台语言

PS:ie8下听说会用flash提交图片,我不知道如何让flash提交带上session/cookie,所以可能在ie8下后台会丢失session/cookie,未经测试。

Ueditor 跨域的问题研究的更多相关文章

  1. HTML5 Web缓存和运用程序缓存(cookie,session)

    这篇文章主要介绍了HTML5 Web缓存和运用程序缓存(cookie,session),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. iOS Swift上弃用后Twitter.sharedInstance().session()?. userName的替代方案

    解决方法如果您仍在寻找解决方案,请参阅以下内容:

  3. 使用Fabric SDK iOS访问Twitter用户时间线

    我试图在这个问题上挣扎两天.我正在使用FabricSDK和Rest工具包,试图为Twitter使用不同的RestAPIWeb服务.我可以使用具有authTokenSecret,authToken和其他值的会话对象的TWTRLogInButton成功登录.当我尝试获取用户时间线时,我总是得到失败的响应,作为:{“errors”:[{“code”:215,“message”:“BadAuthentic

  4. ios – 将iphone应用程序重定向到苹果商店

    我有一个iPhone应用程序,当有可用的升级时,我想提示用户升级,如果他们点击升级,我想将它们重定向到苹果商店.这是怎么做到的?

  5. ios – 如何从Apple Watch调用iPhone上定义的方法

    有没有办法从Watchkit扩展中调用iPhone上的类中定义的方法?根据我的理解,目前在Watchkit和iPhone之间进行本地通信的方法之一是使用NSUserDefaults,但还有其他方法吗?

  6. ios – Oauth突然无法使用iphone(仅安装了FS应用程序)

    我们的iPhone应用程序允许通过oauth通过Foursquare登录.它工作正常,最近停止工作.我们得到的错误是:连接失败:回调uri对此使用者无效.但是,如果用户没有在手机上安装foursquare应用程序,它可以像以前一样正常工作.似乎FS现在正在进行重定向来处理FS应用程序内部的oauth,并且在尝试返回到原始应用程序时失败.通过野生动物园它似乎工作.这是在ios9上.解决方案?

  7. ios – 以http无效的自定义URL方案开头

    我在应用程序中使用了自定义URL方案.我成功地从safari重定向到我的应用程序.就像我已经制作了URL方案“appname”.请检查http://prntscr.com/2cjx0p.我需要使用像iosurlredirectfrommailtoapp这样的解决方案,但我不确定如何设置cookie.我发现我必须首先在我的应用程序中为服务器“http://myappname.com”设置一个cook

  8. ios – NSURLProtocol的抽象方法

    我一直在我的应用程序中使用自定义NSURLProtocol来检测资源并从缓存目录加载(如果可用),或重定向回我的应用程序的服务器.但是,我发现缺少抽象方法的文档,我不知道如何处理我们需要实现的一些抽象方法.我们必须实施:canInitWithRequest很简单,这就是告诉NSURLProtocol您将响应此请求的方式.我不知道如何处理canonicalRequestForRequest:在sta

  9. ios – 如何将视频从AVAssetExportSession保存到相机胶卷?

    在此先感谢您的帮助.解决方法只需使用session.outputURL=…

  10. ios – 使用AVCaptureSession sessionPreset = AVCaptureSessionPresetPhoto拉伸捕获的照片

    解决方法所以我解决了我的问题.这是我现在使用的代码,它工作正常:…重要的输出imagaView:一些额外的信息:相机图层必须是全屏,并且outputimageView也必须是.我希望这些对某些人来说也是有用的信息.

随机推荐

  1. Angular2 innerHtml删除样式

    我正在使用innerHtml并在我的cms中设置html,响应似乎没问题,如果我这样打印:{{poi.content}}它给了我正确的内容:``但是当我使用[innerHtml]=“poi.content”时,它会给我这个html:当我使用[innerHtml]时,有谁知道为什么它会剥离我的样式Angular2清理动态添加的HTML,样式,……

  2. 为Angular根组件/模块指定@Input()参数

    我有3个根组件,由根AppModule引导.你如何为其中一个组件指定@input()参数?也不由AppModalComponent获取:它是未定义的.据我所知,你不能将@input()传递给bootstraped组件.但您可以使用其他方法来做到这一点–将值作为属性传递.index.html:app.component.ts:

  3. angular-ui-bootstrap – 如何为angular ui-bootstrap tabs指令指定href参数

    我正在使用角度ui-bootstrap库,但我不知道如何为每个选项卡指定自定义href.在角度ui-bootstrap文档中,指定了一个可选参数select(),但我不知道如何使用它来自定义每个选项卡的链接另一种重新定义问题的方法是如何使用带有角度ui-bootstrap选项卡的路由我希望现在还不算太晚,但我今天遇到了同样的问题.你可以通过以下方式实现:1)在控制器中定义选项卡href:2)声明一个函数来改变控制器中的散列:3)使用以下标记:我不确定这是否是最好的方法,我很乐意听取别人的意见.

  4. 离子框架 – 标签内部的ng-click不起作用

    >为什么标签标签内的按钮不起作用?>但是标签外的按钮(登陆)工作正常,为什么?>请帮我解决这个问题.我需要在点击时做出回复按钮workingdemo解决方案就是不要为物品使用标签.而只是使用divHTML

  5. Angular 2:将值传递给路由数据解析

    我正在尝试编写一个DataResolver服务,允许Angular2路由器在初始化组件之前预加载数据.解析器需要调用不同的API端点来获取适合于正在加载的路由的数据.我正在构建一个通用解析器,而不是为我的许多组件中的每个组件设置一个解析器.因此,我想在路由定义中传递指向正确端点的自定义输入.例如,考虑以下路线:app.routes.ts在第一个实例中,解析器需要调用/path/to/resourc

  6. angularjs – 解释ngModel管道,解析器,格式化程序,viewChangeListeners和$watchers的顺序

    换句话说:如果在模型更新之前触发了“ng-change”,我可以理解,但是我很难理解在更新模型之后以及在完成填充更改之前触发函数绑定属性.如果您读到这里:祝贺并感谢您的耐心等待!

  7. 角度5模板形式检测形式有效性状态的变化

    为了拥有一个可以监听其包含的表单的有效性状态的变化的组件并执行某些组件的方法,是reactiveforms的方法吗?

  8. Angular 2 CSV文件下载

    我在springboot应用程序中有我的后端,从那里我返回一个.csv文件WheniamhittingtheURLinbrowsercsvfileisgettingdownloaded.现在我试图从我的角度2应用程序中点击此URL,代码是这样的:零件:服务:我正在下载文件,但它像ActuallyitshouldbeBook.csv请指导我缺少的东西.有一种解决方法,但您需要创建一个页面上的元

  9. angularjs – Angular UI-Grid:过滤后如何获取总项数

    提前致谢:)你应该避免使用jQuery并与API进行交互.首先需要在网格创建事件中保存对API的引用.您应该已经知道总行数.您可以使用以下命令获取可见/已过滤行数:要么您可以使用以下命令获取所选行的数量:

  10. angularjs – 迁移gulp进程以包含typescript

    或者我应该使用tsc作为我的主要构建工具,让它解决依赖关系,创建映射文件并制作捆绑包?

返回
顶部