2011-04-12 76 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

相關問題