2011-08-19 60 views
3

我想直接在Javascript中建立多部分表單數據以便將我的數據發送到服務器。我知道有Ajax表單插件,但我真的認爲它們不適合我的需求,因爲我將在瀏覽器中創建二進制數據,並將它發送爲文件提交(我將發佈的服務器要求這樣)。現在服務器錯誤直接使用Javascript發佈MIME多部分數據

我的問題是,建築文本多部分MIME數據的最簡單的例子,在服務器端失敗,出現錯誤:

500 Internal Server Error: Invalid boundary in multipart form 

我試圖代碼減少到最低限度:在這個主。 html(這是它將在以後的服務器代碼中引用的名稱),這兩個html表單都提交html-non-Ajax方式的文本,並且還有一個Javascript函數,它試圖用XmlHttprequest複製該文本:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>Posting MIME Multipart directly in Javascript</title> 

<script> 
function sendMimeMultipart(url, data) { 

    boundary = '---------------------------1504702169761927311267328916' 
    xhr = new XMLHttpRequest(); 

    xhr.open("POST", url); 

    //Build the MIME POST request. 
    var body = "--" + boundary + "\r\n"; 
    body += 'Content-Disposition: form-data; name="contents"\r\n\r\n'; 
    body += data+"\r\n"; 
    body += "--" + boundary + "--"+"\r\n"; 

    var fileSize = body.length 
    xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary); 
    xhr.setRequestHeader("Content-Length", fileSize); 
    xhr.send(body); 
    return true; 
} 

function sendData() { 
    sendMimeMultipart('http://localhost:8080/myhandler', "Hello World!"); 
} 
</script> 
</head> 

<body onload='sendData()'> 

<form action = "myhandler" method = "post" enctype = "multipart/form-data"> 
    <input type = "text" name = "contents"> 
    <input type = "submit"> 
</form> 

</body> 
</html> 

這是請求對象到達服務器使用的形式時:

Request: POST /myhandler 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 
Accept-Language: es-es,es;q=0.8,en-us;q=0.5,en;q=0.3 
Connection: keep-alive 
Content-Length: 187 
Content-Type: multipart/form-data; 
boundary=---------------------------18171295601131570933197493099 
Host: localhost:8080 
Keep-Alive: 115 
Referer: http://localhost:8080/ 
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; es-ES; rv:1.9.2.20) 
Gecko/20110803 Firefox/3.6.20 

-----------------------------18171295601131570933197493099 
Content-Disposition: form-data; name="contents" 

Hello World! 
-----------------------------18171295601131570933197493099-- 

而這使用Javascript函數(sendMimeMultipart)時到達的到服務器的請求對象:

Request: POST /myhandler 
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 
Accept-Language: es-es,es;q=0.8,en-us;q=0.5,en;q=0.3 
Cache-Control: no-cache 
Connection: keep-alive 
Content-Length: 185 
Content-Type: multipart/form-data; charset=UTF-8, 
boundary=---------------------------1504702169761927311267328916 
Host: localhost:8080 
Keep-Alive: 115 
Pragma: no-cache 
Referer: http://localhost:8080/ 
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; es-ES; rv:1.9.2.20) 
Gecko/20110803 Firefox/3.6.20 

-----------------------------1504702169761927311267328916 
Content-Disposition: form-data; name="contents" 

Hello World! 
-----------------------------1504702169761927311267328916-- 

的2個字節中的Content-Length的差異是由於瀏覽器隨機生成邊界,有時更長,有時更短。在這種情況下,它是一個字符的長度,這是兩個邊界事件中兩個字節差異的原因。

我不認爲服務器有這麼多,總線,以防萬一我張貼服務器端代碼。這是Appengine片段,僅供本地主機使用;對「localhost:8080/myhandler」的調用將檢索瀏覽器發佈的「contents」的值,並將其存儲在全局變量中。之後,調用「localhost:8080/show」將顯示先前檢索的文本。正如我之前提到的,如果我們使用表單發送數據,文本內容將被正確保存,並且「show」處理程序將顯示它。但是,如果我們使用Javascript,代碼行:

 contents = self.request.get("contents") 

在MyHandler(代碼如下)中,會產生錯誤。

這裏是服務器代碼:

import cgi 
import datetime 
import logging 
import os 

from google.appengine.ext import db 
from google.appengine.api import users 
from google.appengine.ext import webapp 
from google.appengine.ext.webapp.util import run_wsgi_app 
from google.appengine.api import images 
from google.appengine.ext.webapp import template 
from os import environ 

contents='' 

class mein(webapp.RequestHandler): 
    def get(self): 
     template_values = {} 
     path = os.path.join(os.path.dirname(__file__), 'templates/main.html') 
     self.response.out.write(template.render(path, template_values)) 

class MyHandler(webapp.RequestHandler): 
    def post(self): 
     global contents 
     contents = self.request.get("contents") 

class Show(webapp.RequestHandler): 
    def get(self): 
     global contents 
     self.response.headers['Content-Type'] = "text/plain" 
     self.response.out.write(contents) 

application = webapp.WSGIApplication([ 
    ('/', mein), 
    ('/myhandler', MyHandler), 
    ('/show', Show) 
], debug=True) 

def main(): 
    run_wsgi_app(application) 

if __name__ == '__main__': 
    main() 

爲什麼這應該沒有任何想法?我嘗試了數十萬種不同的東西,但我似乎無法使其工作或理解爲什麼它不行!

非常感謝您的想法和幫助。
所有最好的:

-Javier

+0

你有沒有嘗試從'Content-Type'中刪除'charset'參數?在這種情況下沒有意義。 –

+0

我不知道如何擺脫它。包含它的是Javascript。 :-(如果你看到接受的字符集字段,它看起來像utf-8不應該是一個問題,這個測試僅用於文本內容,而不是二進制文件 –

+0

多部分信息本身並不是真正的文本,但在某種意義上那是在那裏使用的 - 而且每個部分都有自己的內容類型,但是,這似乎不太可能是這個問題 –

回答

2

我遇到試圖手動構建一個HTTP文件上傳時相同的錯誤消息。我通過在Content-Type標題中用分號(;)替換逗號(,)來實現它。在你的情況下,通過更換:

xhr.setRequestHeader("Content-Type", "multipart/form-data, boundary="+boundary); 

有:

xhr.setRequestHeader("Content-Type", "multipart/form-data; boundary="+boundary); 

這似乎是因爲我使用Django(Python)的這個同樣的問題,可能與Python的後端,當我調試它反對一個PHP測試服務器,逗號和分號都起作用。

最後,RFC1867的例子最好使用逗號,所以最終我不確定真正的解決方法,但是分號解決了它。

相關問題