Ich versuche, Multipart Form Data direkt in Javascript zu erstellen, um meine Daten an einen Server zu senden. Ich weiß, dass es Ajax-Formular-Plugins gibt, aber ich denke wirklich, dass sie meinen Bedürfnissen nicht gerecht werden, da ich binäre Daten im Browser erstellen und sie senden werde, als ob es sich um eine Datei handelt (der Server, auf den ich posten werde, erfordert es auf diese Weise).
Mein Problem ist nun, dass das einfachste Beispiel für die Erstellung von Text-Multipart-MIME-Daten auf der Server-Seite mit einem Fehler fehlschlägt:
500 Internal Server Error: Invalid boundary in multipart form
Ich habe versucht, den Code auf ein absolutes Minimum zu reduzieren: In dieser main.html (auf diesen Namen wird später im Servercode Bezug genommen) gibt es sowohl ein HTML-Formular, um Text auf HTML-Non-Ajax-Weise zu übermitteln, als auch eine Javascript-Funktion, die versucht, das mit XmlHttprequest zu replizieren:
<!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>
Dies ist das Request-Objekt, das beim Server ankommt, wenn das Formular verwendet wird:
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--
Und hier das Request-Objekt, das beim Server ankommt, wenn die Javascript-Funktion (sendMimeMultipart) verwendet wird:
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--
Der Unterschied von 2 Bytes bei der Inhaltslänge ist darauf zurückzuführen, dass der Browser die Grenzen nach dem Zufallsprinzip generiert, so dass sie manchmal länger und manchmal kürzer sind. In diesem Fall ist sie um ein Zeichen länger, was den Unterschied von zwei Byte bei den beiden Begrenzungen erklärt.
Ich glaube nicht, dass der Server hat viel mit diesem zu tun, Bus nur für den Fall, dass ich den Server-seitigen Code zu posten. Es handelt sich um ein Appengine-Snippet, das nur für die Verwendung auf dem lokalen Rechner gedacht ist; der Aufruf von "localhost:8080/myhandler" ruft den Wert von "contents" ab, der vom Browser gesendet wurde, und speichert ihn in einer globalen Variable. Danach zeigt ein Aufruf von "localhost:8080/show" den zuvor abgerufenen Text an. Wie ich bereits erwähnt habe, wird der Textinhalt korrekt gespeichert, wenn wir die Daten über das Formular senden, und der "show"-Handler zeigt ihn an. Wenn wir jedoch das Javascript verwenden, wird die Codezeile:
contents = self.request.get("contents")
In MyHandler (Code unten), produziert den Fehler.
Hier ist der Server-Code:
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()
Haben Sie eine Idee, warum dies nicht funktioniert? Ich habe zig verschiedene Dinge ausprobiert, aber ich scheine nicht in der Lage zu sein, es zum Laufen zu bringen oder den Grund zu verstehen, warum es nicht funktioniert.
Vielen Dank im Voraus für Ihre Ideen und Ihre Hilfe.
Ich wünsche Ihnen alles Gute:
-Javier