Extjs文件上传-跨域框架

问题描述 投票:7回答:3

我在Extjs应用程序中有一个fileupload字段。我正在尝试通过以下代码将文件加载到服务器:

var form = Ext.getCmp('ProcImpNewSugFileForm').getForm();
var fileNameStr = Ext.getCmp('ProcImpNewSugFileUpload').getValue().split("\\");
if(fileNameStr){
var filename = fileNameStr[fileNameStr.length-1];
if(form.isValid()){
    form.submit({
        url: '/PISRFileUploader.php',            
        waitMsg: 'Uploading your file...',                
        success: function (formPanel, action, result) {
            Ext.Msg.alert('Msg',"Success: "+action.response.responseText);
        },
        failure: function (formPanel, action, result) {
            Ext.Msg.alert('Msg',"Failure: "+action.response.responseText);
        }
    });
   }
}

但是当我尝试上传任何文件时。该文件正被加载到服务器,但响应如下:

    Failure: {success:false,message:"Blocked a frame with origin 'http://localhost' from accessing a cross-origin frame."}

预先感谢!

extjs file-upload extjs4.2
3个回答
4
投票

这是Uberdude在Sencha论坛中标识的Ext js错误。

问题描述:

[当您使用包含要上载的文件输入的表单进行Ext.Ajax.request时,或将isUpload选项手动设置为true,而不是执行适当的Ajax请求时,Ext以标准HTML方式将表单动态提交给产生隐藏。然后,从iframe中读取json响应主体,以创建伪造的Ajax响应。如果发出上传Ajax请求的页面更改了其document.domain属性,例如, home.example.com上的页面包含来自static.example.com的资源,该资源希望使用javascript进行操作而不会违反浏览器的同源策略,因此都将其document.domain设置为“ example.com”。如果home.example.com然后向home.example.com服务器上的URL发出上载Ajax请求,则写入响应的iframe的document.domain将为“ home.example.com”。因此,当home.example.com页面上Ajax.request中的ExtJS代码尝试从iframe中提取文档主体时,它将被same-origin-policy阻止,并且传递给回调函数的响应将错误地为空responseText。

变通:1.发出上传请求时,将document.domain传递到服务器。2.在服务器响应中,在响应text / html中添加document.domain。

response.setHeader('Content-Type','text / html');response.write('document.domain =“'+ params .__ domain +'”;');response.write(JSON.stringify({msg:'Welcome'+ params.name}));response.end('');

Detail:

请参阅:http://www.sencha.com/forum/showthread.php?136092-Response-lost-from-upload-Ajax-request-to-iframe-if-document.domain-changed


1
投票

[在Wilk的答案中添加其他评论。

如果主机和目的地在不同的端口上,请使用以下解决方案。

index.html文件中,在标题下使用以下行:

<script type=text/javascript>document.domain =document.domain;</script>

以及您的响应以及标题Content-Type:'text/html'和响应

'<html><head><script type=text/javascript>document.domain =document.domain;</script></head><body>{success: true}</body></html>'

这里成功消息是硬编码的,您可以根据输入使用任何自定义消息。

谢谢,Santrupta


1
投票

这是cheftao answer的改进。

如果您需要使用其他域(例如,具有不同端口的localhost),请按照以下步骤操作:

在客户端,在提交表单之前,先单击renew the document domain,然后将其与表单数据一起提交:

  document.domain = document.domain;
  myForm.submit({
    params: {
      domain: document.domain
    },
    ...
  });

在服务器端,使用内容类型text / html并使用以下字符串(此示例通过ExpressJS完成):

var domain = req.body.domain,
    script = '<script type="text/javascript">document.domain = "' + domain + '";</script>',
    body = '<body>' + JSON.stringify({success: true}) + '</body>';

res.send('<html><head>' + script + '</head>' + body + '</html>');

更新:19/05/2016

实际上,最好的解决方案是进行反向代理,以避免此类问题。

© www.soinside.com 2019 - 2024. All rights reserved.