Extjs文件上传 - 跨源框架

时间:2014-03-25 06:55:54

标签: extjs file-upload extjs4.2

我在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."}

提前致谢!

3 个答案:

答案 0 :(得分:4)

这是Uberdude在Sencha论坛中发现的一个Ext js bug。

问题描述:

使用包含要上载的文件输入的表单创建Ext.Ajax.request时,或者手动将isUpload选项设置为true,而不是执行正确的Ajax请求Ext以标准HTML方式将表单提交给动态生成隐藏。然后从iframe中读出json响应主体以创建伪造的Ajax响应。如果发出上传Ajax请求的页面已经改变了其document.domain属性,例如,则会出现问题。 home.example.com上的一个页面包含来自static.example.com的资源,它希望用javascript操作而不违反浏览器的同源政策,所以都将他们的document.domain设置为"示例.COM&#34 ;.如果home.example.com然后向home.example.com服务器上的URL发送Ajax请求,则写入响应的iframe将其document.domain作为" home.example.com&#34 ;。因此,当home.example.com页面上的Ajax.request中的ExtJS代码尝试从iframe中提取文档正文时,它将被同源策略阻止,并且传递给回调函数的响应将错误地为空responseText的。

解决方法:    1.在发出上传请求时将document.domain传递给服务器。    2.在服务器响应中,在响应文本/ 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('&#39);

明细:

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

答案 1 :(得分: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>');

更新:2016年5月19日

实际上,最好的解决方案是进行反向代理,避免出现这种问题。

答案 2 :(得分: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