IE9拒绝处理XML响应。

10

这是与此问题相关的问题。

更新 II中,我根据Jamie的反馈添加了一个脚本。

更新 - tl;dr:

我创建了一个带有临时密钥的fiddle,以便您可以更轻松地查看问题:http://jsfiddle.net/S6wEN/

由于这个问题变得太长了,这是一个总结。

  • 我试图使用imgur API通过跨域XHR更新图像。
  • 为了在实现中抽象细节,我使用了Jquery表单插件(显然,它包含在小提琴里)。
  • 在Chrome、Firefox等浏览器中运行良好,但在IE9中不起作用。
  • 预期结果是更新图像并检索图像类型。

您仍然可以在下面找到详细信息。

谢谢


我有以下HTML:

<body>
<form id="uploadForm" action="http://api.imgur.com/2/upload.xml" method="POST" enctype="multipart/form-data">
    <input type="hidden" name="key" value="MYKEY">
    File: <input type="file" name="image">
    Return Type: <select id="uploadResponseType" name="mimetype">
        <option value="xml">xml</option>
    </select>
    <input type="submit" value="Submit 1" name="uploadSubmitter1">
</form>

<div id="uploadOutput"></div>
</body>

基本上,我有一个表单通过跨域XHR上传图像到imgur。为了管理复杂的细节,我使用Jquery Form Plugin,这个插件工作得很好。然而,当我尝试发送图像到imgur并接收xml响应时,在IE9中它并不如预期地工作(我还没有在IE8中测试,但我不指望会有好消息)。在Chrome和Firefox中它运行得很好。以下是JavaScript部分:

(function() {
$('#uploadForm').ajaxForm({
        beforeSubmit: function(a,f,o) {
           o.dataType = $('#uploadResponseType')[0].value;
           $('#uploadOutput').html('Submitting...');
        },

        complete: function(data) {
        var xmlDoc = $.parseXML( data.responseText ),
            $xml = $( xmlDoc );
            $('#uploadOutput').html($xml.find('type'));

        }
    });
})();  

在IE9中,我遇到了以下错误:

SCRIPT5022: Invalid XML: null 
jquery.min.js, line 2 character 10890

XML5619: Incorrect document syntax. 
, line 1 character 1

我还尝试了 Jquery Form 插件页面提供的示例,它只使用了Javascript,但并没有起到帮助作用。显然,第一个涉及Jquery的错误消失了,但我无法获得期望的结果(在这种情况下,是位于id为 "uploadOutput" 的div中的image/jpeg)。

当我查看IE9中的控制台时,得到了以下信息:

URL Method  Result  Type    Received    Taken   Initiator   Wait‎‎  Start‎‎ Request‎‎   Response‎‎  Cache read‎‎    Gap‎‎
http://api.imgur.com/2/upload.xml   POST    200 application/xml 1.07 KB 7.89 s  click   2808    93  5351    0   0   0

并作为响应主体:

<?xml version="1.0" encoding="utf-8"?>
<upload><image><name/><title/><caption/><hash>xMCdD</hash>  
<deletehash>Nb7Pvf3zPNohmkQ</deletehash><datetime>2012-03-17 01:15:22</datetime>
<type>image/jpeg</type><animated>false</animated><width>1024</width
<height>768</height><size>208053</size><views>0</views><bandwidth>0</bandwidth></image
<links><original>http://i.imgur.com/xMCdD.jpg</original
<imgur_page>http://imgur.com/xMCdD</imgur_page>
<delete_page>http://imgur.com/delete/Nb7Pvf3zPNohmkQ</delete_page>
<small_square>http://i.imgur.com/xMCdDs.jpg</small_square>
<large_thumbnail>http://i.imgur.com/xMCdDl.jpg</large_thumbnail></links></upload>

一切都很顺利,但出于某种原因,我无法将该信息处理到HTML页面中。为了确保问题不是出在XML上,我进行了验证。当然,它是有效的。

那么,IE9有什么问题呢?

更新:

另一种获取XML的方法在Chrome和Firefox中可行,但在IE9中不可行:

(function() {
$('#uploadForm').ajaxForm({
        dataType: "xml",
        beforeSubmit: function(a,f,o) {
           o.dataType = $('#uploadResponseType')[0].value;
           $('#uploadOutput').html('Submitting...');
        },

        success: function(data) {
            var $xml = $( data ),
                element = $($xml).find('type').text();
                alert(element);
        }
    });
})();  

更新2::

<!DOCTYPE html>
<html>
    <body>
    <form id="uploadForm" action="http://api.imgur.com/2/upload.xml" method="POST" enctype="multipart/form-data">
        <input type="hidden" name="key" value="00ced2f13cf6435ae8faec5d498cbbfe">
        File: <input type="file" name="image">
        Return Type: <select id="uploadResponseType" name="mimetype">
            <option value="xml">xml</option>
        </select>
        <input type="submit" value="Submit 1" name="uploadSubmitter1">
    </form>

    <div id="uploadOutput"></div>
    </body>
</html>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="jquery.form.js"></script>
​<script>
(function() {

    var options = { 
        // target:        '#output1',   // target element(s) to be updated with server response 
        //beforeSubmit:  showRequest,  // pre-submit callback 
        success: afterSuccess,  // post-submit callback 
        complete: afterCompletion,
        // other available options: 
        //url:       url         // override for form's 'action' attribute 
        type:      'POST',        // 'get' or 'post', override for form's 'method' attribute 
        dataType:  'xml'        // 'xml', 'script', or 'json' (expected server response type) 
        //clearForm: true        // clear all form fields after successful submit 
        //resetForm: true        // reset the form after successful submit 

        // $.ajax options can be used here too, for example: 
        //timeout:   3000 
    }; 

    function process_xml(xml) {
      var type = $(xml).find('type').text() ;
      return type;
      // Find other elements and add them to your document
    }


    function afterSuccess(responseText, statusText, xhr, $form)  { 
        // for normal html responses, the first argument to the success callback 
        // is the XMLHttpRequest object's responseText property 

        // if the ajaxForm method was passed an Options Object with the dataType 
        // property set to 'xml' then the first argument to the success callback 
        // is the XMLHttpRequest object's responseXML property 

        // if the ajaxForm method was passed an Options Object with the dataType 
        // property set to 'json' then the first argument to the success callback 
        // is the json data object returned by the server 
        var $xml = process_xml(responseText);
        console.log('success: ' + $xml);
    } 


    function afterCompletion(xhr,status){
          if(status == 'parsererror'){

            xmlDoc = null;

            // Create the XML document from the responseText string

            if(window.DOMParser) {

              parser = new DOMParser();
              xml = parser.parseFromString(xhr.responseText,"text/xml");

            } else {

              // Internet Explorer
              xml = new ActiveXObject("Microsoft.XMLDOM");
              xml.async = "false";
              xml.loadXML(xhr.responseText);

            }

          }

          console.log('complete: ' + process_xml(xhr.responseText));
    }

$('#uploadForm').ajaxForm(options);
})();  
</script>

提前感谢。


你是否使用Fiddler2运行IE来检查结果。IE在内容编码头方面非常严格,我怀疑虽然文档在文档中标记为UTF-8,但服务器可能没有指定字符集。其他浏览器通常会默认使用UTF-8。 - Tracker1
我已经尝试过了,结果还是一样的。我没有在这里发布它,因为它需要一个密钥才能工作,所以在这种情况下没有实际用途。不过我稍后会再试一次。 - r_31415
我刚刚添加了一个带有临时密钥的小提琴。 - r_31415
顺便说一下,我不确定这是否与编码相关的问题,因为这里提供的示例(http://malsup.com/jquery/form/#file-upload)运行良好。 - r_31415
您发布的XML无效:第5行“</image”没有闭合“>”。或者这只是一个发布时的打字错误? - Andrew Morton
@AndrewMorton 我已经验证了,确实是一个打字错误,当我在这里复制它时。每个标签中的响应都包括“>”。 - r_31415
4个回答

6

当涉及到接受和解析XML时,IE倍感棘手。尝试使用以下代码:

function process_xml(xml) {
  var type = $(xml).find('type').text() ;
  $('#type').html(type) ;

  // Find other elements and add them to your document
}

$(function() {
  $('#uploadForm').ajaxForm({ 
    dataType: "xml", // 'xml' passes it through the browser's xml parser
    success: function(xml,status) {

      // The SUCCESS EVENT means that the xml document
      // came down from the server AND got parsed successfully
      // using the browser's own xml parsing caps.

      process_xml(xml);

      // Everything goes wrong for Internet Explorer
      // when the mime-type isn't explicitly text/xml.

      // If you are missing the text/xml header
      // apparently the xml parse fails,
      // and in IE you don't get to execute this function AT ALL.

    },
    complete: function(xhr,status){

      if(status == 'parsererror'){

        xmlDoc = null;

        // Create the XML document from the responseText string

        if(window.DOMParser) {

          parser = new DOMParser();
          xml = parser.parseFromString(xhr.responseText,"text/xml");

        } else {

          // Internet Explorer
          xml = new ActiveXObject("Microsoft.XMLDOM");
          xml.async = "false";
          xml.loadXML(xhr.responseText);

        }

        process_xml(xml);

      }
    },
    error: function(xhr,status,error)
    {
      alert('ERROR: ' + status) ;
      alert(xhr.responseText) ;
    }
  });
});

同时,在调试过程中使用 alert() 来提供有关传递的信息的反馈。 编辑 关键是确保您的 XML 文件是“格式正确”的,即不包含任何语法错误。您需要以以下内容开始 XML 文件:
<?xml version="1.0"?>

这并不是服务器问题,而是因为您的浏览器(例如Internet Explorer)认为 XML 格式不正确,从而导致错误。此错误来自于您的浏览器,表明您的 XML 格式不正确。您可以通过以下 $.ajax()设置手动设置要返回的标头:

dataType: ($.browser.msie) ? "text" : "xml",
accepts: {
    xml: "text/xml",
    text: "text/xml"
}

还有一种做法是通过请求特定的标头(header)来实现:

headers: {Accept: "text/xml"},

application/xmltext/xml 的内容类型差异很小(基于每个XML的字符集),但如果您想了解更多信息,可以阅读此文章


我认为你做得很好。success()没有被调用,而complete()运行了,但显然没有得到任何响应。根据你的评论,它缺少text/xml头文件。我在IE中检查了头文件,但是我看到的是Content type: application/xml。那不够吗?无论如何,这是一个服务器问题,对吧? - r_31415
当响应头为application/xml时,它是否有效?如果无效,我在我的问题中包含了一个快速编辑,手动设置AJAX请求的响应头。 - hohner
好的,看起来它更接近解决方案了,但不幸的是,添加任何这些片段都会引发在Chrome、Firefox和IE中加载imgur.com的xml页面。而成功并没有开始。 - r_31415
哦...那只有当我将它添加到“beforeSubmit”函数中时才会发生,但如果我像这样将它们与其他内容一起放置:“success: afterSuccess, complete: afterCompletion, dataType: ($.browser.msie) ? "text" : "xml", accepts: { xml: "text/xml", text: "text/xml" }”,什么也不会发生。顺便说一下,<?xml version="1.0"?>已经正确设置。 - r_31415
你确定你在那个代码片段里没有做任何更改吗?虽然也许这就是你看到的。在那个代码片段中,我将你的设置不正确地添加到了“beforeStart”中,所以在代码片段中你会得到整个XML字符串。但是如果你在浏览器中尝试它,它不起作用(我认为你会得到IE解析的XML文件)。现在,如果我删除beforeStart并在“type”之后添加你的设置,我在Chrome中得到了这个(成功:image/jpeg upload2.html:87complete:image/jpeg),这是正确的,在IE中得到了(LOG:complete:),这当然是不正确的。虽然,正如你所说,响应是200。 - r_31415
显示剩余2条评论

1

或许可以试试这个?我在谷歌地图门店定位器中使用它。我注意到 $.parseXML 实际上在内部执行了这个操作,但是它被包含在 try/catch 中,并且它说你的 data 是 null(这很奇怪?)

      var xml;
     if (typeof data == "string") {
       xml = new ActiveXObject("Microsoft.XMLDOM");
       xml.async = false;
       xml.loadXML(data);
     } else {
       xml = data;
     }

来自jQuery:

// Cross-browser xml parsing
parseXML: function( data ) {
    var xml, tmp;
    try {
        if ( window.DOMParser ) { // Standard
            tmp = new DOMParser();
            xml = tmp.parseFromString( data , "text/xml" );
        } else { // IE
            xml = new ActiveXObject( "Microsoft.XMLDOM" );
            xml.async = "false";
            xml.loadXML( data );
        }
    } catch( e ) {
        xml = undefined;
    }
    if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
        jQuery.error( "Invalid XML: " + data );
    }
    return xml;
},

我认为非IE部分存在问题,因为现在我遇到了未捕获的异常(无效的XML:[object Document]),但在IE9中我没有看到任何错误,然而,即使响应正文显示正确的XML文档,它也不执行任何操作。 - r_31415

1

我以前用过那个插件。如果我没记错的话,它是使用 iframe 来获取信息,然后读取 iframe 中的内容。内容存储在 responseText 属性中。但 IE 可能比其他浏览器有更严格的规则。你尝试打印出 data.responseText 的值了吗?

如果该值不是 XML 字符串。我很抱歉地说,该 API 不适用于 Javascript。我的经验是,使用 JSONP 并操作脚本标签是跨域 XHR 的最佳方式。我认为这个插件没有做到这一点。


感谢您的回答。当我尝试在IE9中打印data.responseText时,什么也没有输出(虽然在其他浏览器中它可以正常工作),但响应是有效的XML。此外,插件文档页面中的示例在IE9中也可以正常工作,因此如果这是由插件特定的问题引起的话,我会非常惊讶。 - r_31415
这证实了“无法访问iframe”的假设 - 数据返回,但无法读取。 - boisvert
API并不是为客户端代码而设计的。因此,唯一的方法是使用服务器端代码获取XML并进行格式化。 - einstein

1

js 代码:

    $(function() {
        $('#uploadForm').ajaxForm({
            dataType : 'xml', // OR $('#uploadResponseType option:selected').val()
            beforeSubmit : function(a, f, o) {
                $('#uploadOutput').html('Submitting...');
            },
            success : function(data) {
                var original = $(data).find('links').find('original').text();
                $('#uploadOutput').html('<img src="' + original + '" alt="" />');
            }
        });
    });

php 代码:

<?
    $api_key = "****************************";

    $file    = getcwd() . '/' . basename( $_FILES['image']['name'] );
    move_uploaded_file($_FILES['image']['tmp_name'], $file);

    $handle  = fopen($file, "r");
    $data    = fread($handle, filesize($file));

    $pvars   = array('image' => base64_encode($data), 'key' => $api_key);
    $post    = http_build_query($pvars);

    $curl    = curl_init();
    curl_setopt($curl, CURLOPT_URL, 'http://api.imgur.com/2/upload.xml');
    curl_setopt($curl, CURLOPT_TIMEOUT, 30);
    curl_setopt($curl, CURLOPT_POST, 1);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $post);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-type: application/x-www-form-urlencoded"));
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    $xml = curl_exec($curl); 
    curl_close ($curl);

    unlink($file);

    header('Content-type: text/xml'); 
    echo $xml;
?>

感谢您的努力,但也许您没有阅读链接(https://dev59.com/JWHVa4cB1Zd3GeqPnYLM)。我正在寻找一种跨域XHR Javascript解决方案。 - r_31415

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接