2011-04-12 74 views
0

我正在试图解决此问题。我已经实现了一个类似ColdFusion的Ajax文件上传,它使用一个隐藏的框架上传一个文件,然后抓取该框架返回的内容。它基于这篇文章:http://www.bennadel.com/blog/1244-ColdFusion-jQuery-And-AJAX-File-Upload-Demo.htm当html传入JSON数据包时出现Javascript错误

所以,一切工作都很好,除了当我发回数据中的HTML。因此,如果您查看下面的代码,我已经提供了将数据流式传输回隐藏帧的操作页面。第一行工作,第二行html不行。

<!--- Create the return HTML. Remember, we are going to be treating the BODY of the returned document as if it were a JSON string. ---> 
    <cfsavecontent variable="strHTML"> 

     <cfset var sResponse = {} /> 
     <!--- THIS WORKS ---> 
     <cfset sResponse = {SUCCESS = true, ERRORS = [], DATA = "Hello World", RETURNID=""} /> 
     <!--- THIS DOES NOT WORK ---> 
     <cfset sResponse = {SUCCESS = true, ERRORS = [], DATA = #HtmlEditFormat('<div>Hello World</div>')#", RETURNID=""} /> 

     <cfoutput> 
      <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
      <html> 
      <head></head> 
      <body>#SerializeJSON(sResponse)#</body> 
      </html> 
     </cfoutput> 
    </cfsavecontent> 

<!--- Create binary response data. ---> 
<cfset binResponse = ToBinary(ToBase64(strHTML)) /> 

<!--- Tell the client how much data to expect. ---> 
<cfheader name="content-length" value="#ArrayLen(binResponse)#" /> 

<!--- Stream the "plain text" back to the client .---> 
<cfcontent type="text/html" variable="#binResponse#" /> 

下面是做这一切的JavaScript。 HTML返回时出错的行是:

//假设我们的返回数据是JSON格式,请评估body html以获取我们的返回数据。 var objData = eval(“(”+ jBody.html()+“)”);

//ShareForm Photo Upload Form Process (simulated Ajax) 
$(document).ready(function() { 
    // Attach an event to the submit method. Instead of submitting the actual form to the primary page, we are going to be submitting the form to a hidden iFrame that we dynamically create. 
    $("#frmShareForm").submit(
     function(objEvent){ 
      var jThis = $(this); 
      var photoUploadAction = $("#photoUploadAction").val(); 

      // Create a unique name for our iFrame. We can do this by using the tick count from the date. 
      var strName = ("uploader" + (new Date()).getTime()); 

      // Create an iFrame with the given name that does not point to any page - we can use the address "about:blank" to get this to happen. 
      var jFrame = $("<iframe name=\"" + strName + "\" src=\"about:blank\" />"); 

      // We now have an iFrame that is not attached to the document. Before we attach it, let's make sure it will not be seen. 
      jFrame.css("display", "none"); 

      // Since we submitting the form to the iFrame, we will want to be able to get back data from the form submission. 
      // To do this, we will have to set up an event listener for the LOAD event of the iFrame. 
      jFrame.load(
       function(objEvent){ 
        // Get a reference to the body tag of the loaded iFrame. We are doing to assume that this element will contain our return data in JSON format. 
        var objUploadBody = window.frames[ strName ].document.getElementsByTagName("body")[ 0 ]; 

        // Get a jQuery object of the body so that we can have better access to it. 
        var jBody = $(objUploadBody); 

        // Assuming that our return data is in JSON format, evaluate the body html to get our return data. 
        var objData = eval("(" + jBody.html() + ")"); 
        alert(objData); 

        // A JSON-format struct is returned that will be used to do callback functionality 
        SharePhotoAjaxResponseHandler(objData); 

        // Remove the iFrame from the document. Because FireFox has some issues with "Infinite thinking", let's put a small delay on the frame removal. 
        setTimeout 
        (
         function() 
         { 
          jFrame.remove(); 
         }, 100 
        ); 
       } 
      ); 

      // Attach to body. 
      $("body:first").append(jFrame); 

      // Now that our iFrame it totally in place, hook up the frame to post to the iFrame. 
      jThis 
       .attr("action", photoUploadAction) 
       .attr("method", "post") 
       .attr("enctype", "multipart/form-data") 
       .attr("encoding", "multipart/form-data") 
       .attr("target", strName); 
    }); 
}); 

的JavaScript错误我得到的通常是这样的: “未结束的正则表达式文本”

我也曾尝试CFM页面上卸下SerialiseJson,并在JavaScript中的eval,这既导致其他js错误。我也尝试删除周围的html以及将.html()更改为.text(),删除eval()及其所有组合。没有运气。

请有人告诉我问题是什么。我知道我不能离得很远,因为它没有HTML。

感谢

更新:我跑了ColdFusion的产生通过JSON验证的JSON输出,但失败,因为(从我所看到的),双引号:

{""RETURNID"":"""",""DATA"":""&lt;div&gt;Hello World&lt;\/div&gt;"",""SUCCESS"":true,""ERRORS"":[]} 

现在我真的不知道为什么Coldfusion正在做双引号?有人有主意吗?

+1

不要使用'eval',使用真正的JSON解析器:https://开头的github .com/douglascrockford/JSON-js – Quentin 2011-04-12 16:25:32

+1

如果您向我们展示了一些JSON而不是生成JSON的某些CF,它会有所帮助。 – Quentin 2011-04-12 16:26:04

+0

嗨,再次 - 我确实在其他地方使用JSON解析器来处理我的ajax,但我不知道在这种情况下如何使用它,因为没有真正的Ajax发生。 – Cheeky 2011-04-12 18:32:40

回答

2

HTML是响应被解释为格式不正确的HTML。 SerializeJSON将"</div>"中的“/”转义为"<\/div>",导致HTML解析器查看格式不正确的HTML。 在JavaScript方面,"/div"看起来像一个不好的正则表达式。

为此,您必须强制浏览器不为您解释数据。 发送脚本块中的数据与错误类型(因此浏览器不运行脚本)。

ColdFusion的:

<!--- Create the return HTML. Remember, we are going to be treating the BODY of the returned document as if it were a JSON string. ---> 
<cfsavecontent variable="strHTML"> 

    <cfset sResponse = {SUCCESS = true, ERRORS = [], DATA = "<div>Hello World</div>", RETURNID=""} /> 
    <cfoutput> 
     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
     <html> 
     <head></head> 
     <body><script id="data" type="json">#SerializeJSON(sResponse)#</script> 
     </html> 
    </cfoutput> 
</cfsavecontent> 

<!--- Create binary response data. ---> 
<cfset binResponse = ToBinary(ToBase64(strHTML)) /> 

<!--- Tell the client how much data to expect. ---> 
<cfheader name="content-length" value="#ArrayLen(binResponse)#" /> 

<cfcontent type="text/html" variable="#binResponse#" /> 

在broswer的JSON源使用发现

var objUploadBody = window.frames[ strName ].document.getElementById("data"); 

// Get a jQuery object of the body so that we can have better access to it. 
var jBody = $(objUploadBody); 

// Assuming that our return data is in JSON format, evaluate the body html to get our return data. 
var objData = eval("(" + jBody.html() + ")"); 
+0

感谢您的建议,但在每次尝试使用您的建议时,数据都是空白的。 – Cheeky 2011-04-12 17:31:47

+0

@Paul Perigny:嗨保罗 - 好的,废掉我以前的评论。在一些睡眠之后,我再次看着你的解决方案,看到我已经排除了'var objUploadBody = window.frames [strName] .document.getElementById(“data”);'测试时。我现在再次测试,并且我设法使用您的建议得到它的工作,除了我得到一个错误在JavaScript“无效标签”,它似乎与数据获取。我会调查。但是,到目前为止,即使出现错误,一切仍在运行,所以现在只需要解决这个错误。 – Cheeky 2011-04-13 06:01:24

+0

@Paul Perigny:好的,保罗,我已经确定,它正是你用来传递数据的JavaScript脚本标记。提交页面的那一分钟加载了错误,所以即使向eval中的数据添加括号也没有帮助,因为错误发生在表单加载的那一刻(.attr(“action”,photoUploadAction))。 :(所以它的工作,但它没有任何其他方式来解决这个??我们是如此接近! – Cheeky 2011-04-13 06:40:39

0

的JavaScript错误我得到的通常 这样的: “未终止定期 表达字面”

检查JSON。你可以通过JSONLint来运行它,看看它是否有效。它可能不是,根据您的错误信息。

+0

嗨 - 的确你是对的。看到我上面的更新。我发布了不正确的JSON。它由Coldfusion生成,所以我不确定它为什么用双引号输出? – Cheeky 2011-04-12 18:34:49

0

您正在将JSON推入HTML文档的<body>

浏览器将它解释为HTML,并对其进行纠错(做这样的事情转换&&amp;并丢弃未在你已经把他们的地方允许的元素。

然后将其拉出。因此,使用

该解决方案jQuery的html()方法,这将让HTML源代码,而不是你想要的文字是:在JSON

  1. 编码任何实体您需要一个HTML表示。 JSON字符串,而不是原始字符串。我不知道如何做到这一点的CF但必须有一个相当于encode_entities/htmlspecialchars /等
  2. 获取text()不是html()

(顺便说一句:这就是你需要做的,不是一切一个替代品列表)

+0

嗨大卫。我尝试了基于这里的建议,使用.html(),.text(),删除eval(),删除SerializeJson()等每一个可能的组合。每次它是一个或另一个JavaScript错误。然而,我已经实现了你已经在代码中更新过的HtmlEditFormat()的建议,但即使是其他组合也没有帮助。我倾向于认为它肯定有某种方式与JSON输出有关。 – Cheeky 2011-04-12 18:29:25

0

问题是,你从服务器内嵌入更多的HTML内的JSON响应。 AJAX调用的JSON响应应包含仅限 JSON文本,而不包含其他内容。

由于您将它嵌入到HTML中,然后用DOM调用来检索它,很可能浏览器完全被html内的json中的html弄糊涂并且损坏了DOM。

试试这个,而是:

<cfoutput>#SerializeJSON(sResponse)#</cfoutput> 

var objData = eval(jBody); 

不过,因为其他answeres所指出的那样,你不应该为这种使用eval。还有更安全的方式将JSON数据解析回javascript对象而不是eval。

+0

嗨,这不是一个Ajax调用,而是一个类似Ajax的调用,它使用html框架来提交内容并接收响应。尽管如此,我尝试了你的建议,以及你和其他人的组合,但迄今为止还没有运气。 – Cheeky 2011-04-12 18:34:02

相关问题