2017-08-04 92 views
1

在我的extjs6项目中,我正在上传一个文件到我的webapi。 (使用窗体... fileuploadfield)文件成功上传,它应该返回一个简单的字符串列表,但即使文件上传得当,在我的控制器它总是返回FAILURE form.submit。原因...“阻止了原始帧”http://localhost:57007“访问跨源帧。”extjs form.submit由于“访问一个跨源帧”而失败

我相信我在某个地方阅读,当我做form.submit时,它会创建一些导致交叉原点的框架。

通常我不在乎它是否总是返回失败,因为作业仍然完成...但我想返回一些不能工作的东西,如果失败了。有人能以安全的方式帮助我做到这一点吗?

PANEL

    xtype: 'form', 
       fileUpload: true, //(1) 
       width: 500, 
       frame: true, 
       title: 'Client Recap Upload Form', 
       bodyPadding: '10 10 10 10', 
       margin: '10px 10px 10px 10px', 
       standardSubmit: false, 
       defaults: { 
        anchor: '100%', 
        allowBlank: false, 
        msgTarget: 'side', 
        labelWidth: 50 
       }, 
       items: [{ 
        xtype: 'fileuploadfield', 
        emptyText: 'Select a file', 
        fieldLabel: 'Filename', 
        name: 'file', 
        buttonText: 'Choose a file' 
       }], 
       buttons: [ 
        { 
         text: 'Upload', 
         listeners: { 
          click: 'onButtonFileUpload' 
         } 
        } 
       ] 

控制器

onUploadClientRecap: function (field, e, options, mid) { 

    var me = this; 

    if (field.up('form').getForm().isValid()) { 
     field.up('form').getForm().submit({ 
      url: ExtApplication4.util.GlobalVar.urlTM_UploadClientRecap + mid, 
      waitMsg: 'Uploading your file...', 
      success: function (form, o) 
      { 
       Ext.Msg.show({ 
        title: 'Result', 
        msg: o.response.responseText,//.result.result, 
        buttons: Ext.Msg.OK, 
        icon: Ext.Msg.INFO 
       }); 
      }, 
      failure: function (form, o) 
      { 
       debugger; 
       Ext.Msg.show({ 
        title: 'Result', 
        msg: 'File Uploaded...', 
        buttons: Ext.Msg.OK, 
        icon: Ext.Msg.INFO 
       }); 
      } 
     }); 
    } 
}, 

WEB API

 [Route("api/tradematch/UploadClientRecap/{mid}")] 
    [HttpPost] 
    public List<string> UploadClientRecap(HttpRequestMessage request, int mid) 
    { 
     HttpContext context = HttpContext.Current; 
     HttpPostedFile postedFile = context.Request.Files["file"]; 

     return _repo.UploadClientRecap(postedFile, mid); 
    } 
在我的WebAPI

我也在我的Application_BeginRequest

 protected void Application_BeginRequest(object sender, EventArgs e) 
    { 
     string[] allowedOrigin = new string[5]; 
     allowedOrigin[0] = "http://localhost:57007"; 
     allowedOrigin[1] = "http://x.com"; 
     allowedOrigin[2] = "https://x.com"; 
     allowedOrigin[3] = "https://www.p.com"; 
     allowedOrigin[4] = "http://www.p.com"; 

     var origin = HttpContext.Current.Request.Headers["Origin"]; 
     if (origin != null && allowedOrigin.Contains(origin)) 
     { 
      HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", origin); 

      if (HttpContext.Current.Request.HttpMethod == "OPTIONS") 
      { 
       HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache"); 
       HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST"); 
       HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization, X-Requested-With"); 
       HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000"); 
       HttpContext.Current.Response.End(); 
      } 
     } 
运行此代码

尝试新的WebAPI返回重定向

 [Route("api/tradematch/UploadClientRecap/{mid}")] 
    [HttpPost] 
    public HttpResponseMessage UploadClientRecap(HttpRequestMessage request, int mid) 
    { 
     HttpContext context = HttpContext.Current; 
     HttpPostedFile postedFile = context.Request.Files["file"]; 

     var response = Request.CreateResponse(HttpStatusCode.Moved); 
     response.Headers.Location = new Uri("http://www.google.com/" + "&output=crudeOil"); 
     return response; 

     //return _repo.UploadClientRecap(postedFile, mid); 
    } 
+0

你究竟在哪里提交文件? 一般的解决方案是通过发送适当的http头来显式地允许CORS在涉及的域之间传递,但是从你的片段中不可能给出任何具体的建议...... – Mastacheata

+0

难道你的前端运行在不同于你的api的端口上吗?您可以使用反向代理来使它们在同一来源下可用 - 或者像Mastacheata之前说过的那样启用CORS,更多位于:https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS – devbnz

+0

@ Mastacheata我刚刚更新了我的代码,向您展示了webapi。这是否给你你需要的信息? – solarissf

回答

0

文件的上传(POST请求)是不受CORS;然而,访问iframe(其上下文当前是跨域起源)的主体当然受制于它,并且是跨域问题可能发生的地方(我已经看过很多次了)。我绕过这个

一种方法是采用类似于这个jQuery插件做的方法:https://github.com/blueimp/jQuery-File-Upload/wiki/Cross-domain-uploads#cross-site-iframe-transport-uploads

总之,在你的上传处理代码,您重定向到您的客户端应用程序,并通沿期望的数据,你希望作为在查询字符串中上传的结果(例如,上传时间,文件名等)可用。然后,在您的客户端应用程序中,创建一个简单的重定向页面,该页面将处理传入的查询字符串并对其进行适当处理。

的原因,所有的工作原理是iframe的那个内容将来自同一个域被最终担任该请求,一旦重定向发生:

iframe src = cross-domain url 

=> POST upload 
=> Process upload 
=> Redirect response to same domain as original client app 

iframe src = original requesting client 

正因为如此,就可以顺利阅读内容通过JS,而不用跨过iframe的跨域策略。

这里是一个什么样的上传代码(节点)可能看起来像创建重定向一个非常简单的例子:

app.post('/api/photo', function(req, res) { 
    if (done == true) { 
     var params = { 
      sometext: "I am some text", 
      success: true, 
      msg: 'The upload was successful', 
      filename: 'Avatar.png' 
     }; 

     res.redirect('http://myapp.com/results.html?data=' + JSON.stringify(params)); 
    } 
}); 

然后,您的重定向文件处理响应:

<html> 
    <head> 
     <meta charset="utf-8"> 
     <title>Cross-Domain Upload Redirect Page</title> 
    </head> 
    <body> 
     <script> 
      // strip off "?data="... 
      var data = window.location.search.slice(6), 
       decodedJSON = decodeURIComponent(data); 
      // set JSON string into innerText and textContent 
      // so Ext.data.Connection can treat it 
      // the same as regular iframe uploads 
      document.body.innerText=document.body.textContent=decodedJSON; 
    </script> 
</body> 

+0

我试图理解这一点,但我对这一些很新。从你创建重定向的文章开始开始,你在节点中说明了这一点,我该怎么做?它在我的前端还是在我的webapi?我的前端是一个JavaScript框架EXTJS,并且前端API是c# – solarissf

+0

重定向将发生在正在处理上传的位置;在这种情况下,在你的应用服务器代码中。 –

+0

我改变了我的webapi代码来返回重定向,但我不知道如何实际处理它的前端。我收到错误请求的URL代码未在服务器上找到。很可能是因为我刚刚完成。你有一个如何处理在extjs或JavaScript重定向的例子吗? – solarissf