IE iframe无法正确处理application / json响应

时间:2013-07-17 14:06:33

标签: javascript json internet-explorer iframe ajaxform

我目前正在使用ASP.NET Web API将ASP.NET MVC网站的某些部分升级为RESTful。我们正在转向更RESTful设计的功能之一是文件上传。对于客户端,我们使用jquery插件ajaxForm来包装iframe的创建,该iframe将提交包含文件输入元素的表单。这对ASP.NET MVC很有用。

当更改它以使用我们的Web API端点,它返回Content-Type为“application / json”的响应时,我们注意到Internet Explorer 9的问题。似乎从未调用过ajaxForm成功函数。据我所知,似乎IE中的iframe将Content-Type为“application / json”的响应正文解释为要下载的文件附件。这意味着它永远不会触发iframe的“已加载”事件,这意味着永远不会触发ajaxForm onload事件处理程序,并且永远不会调用我们的ajaxForm成功函数。

我们也注意到了IE 7中的问题,但我们无法在Firefox或Chrome的最新版本中重新创建此问题,即使强迫他们使用iframe而不是使用FormData的File API。

现在要解决此问题,我现在强制将响应Content-Type恢复为“text / plain”,这是我们之前从处理文件上载的ASP.NET MVC控制器操作返回的内容。这使一切都恢复了。

我的问题:

  • 有没有办法可以将Web API响应Content-Type保持为“application / json”并让IE正确解释它?
  • 使用IE和Web API时,是否有更好的文件上传方式?也许是一个不同的插件或更好的技术?

其他限制:我不能在本网站上使用ActiveX或Flash。我可以使用不同的插件,但前提是它具有一般的跨浏览器支持。 (IE,Chrome,Firefox,Safari等)

我的HTML:

<form id="uploadFormId" action="" method="post" enctype="multipart/form-data" encoding="multipart/form-data">
    <input type="file" name="files[]"/>
</form>

我的javascript:

function onFileChange( e ) {
    if ( e.type === e.originalEvent.type ) {
        var filePath = $( e.currentTarget ).val();
        if ( filePath !== '' ) {
            $( this ).closest( 'form' ).submit();
        }
    }
};

$( function() {
    $( '#uploadFormId' ).ajaxForm( {
        url: "api/Files/1234",
        dataType: 'json',
        success: function ( response ) { 
            alert( response );
        },
        error: function ( xhr, status, error ) { 
            alert( status );
        }
    } );
    $( '#uploadFormId input[type="file"]' ).bind( 'change', onFileChange );
});

“application / json”响应标头(在IE中不起作用):

Cache-Control:no-cache
Content-Length:337
Content-Type:application/json; charset=utf-8
Date:Wed, 17 Jul 2013 13:10:47 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/8.0
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET

“text / plain”响应标头(适用于IE):

Cache-Control:no-cache
Content-Length:322
Content-Type:text/plain
Date:Wed, 17 Jul 2013 13:17:24 GMT
Expires:-1
Pragma:no-cache
Server:Microsoft-IIS/8.0
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET

1 个答案:

答案 0 :(得分:9)

当ajaxForm使用iframe提交模式时,调用的响应必然会在iframe的主体中呈现。这意味着它必须是浏览器可以呈现的内容类型 - 通常是HTML,但text/plain也可能正常工作。但是,浏览器无法将application/json呈现为页面。

使用text/plain时也存在一个特定问题,因为浏览器可能会内容嗅探它,并且如果数据中看起来像HTML标记,则将资源视为HTML。如果您的JSON中包含用户提供的数据,则可能允许某人将可执行JavaScript注入您的站点(XSS攻击)。

根据ajaxForm doc的建议,您应该检测到来自iframe帖子而不是AJAX的调用,并在这种情况下返回带有textarea包装的text/html响应:

  

为了解释使用iframe模式时脚本和JSON响应的挑战,Form Plugin允许将这些响应嵌入到textarea元素中,建议您在与文件结合使用时对这些响应类型执行此操作上传和旧浏览器。