4 Stimmen

Serverfehler beim direkten Einstellen von MIME-Multipart-Daten mit Javascript

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

2voto

Arahman Punkte 404

Ich habe die gleiche Fehlermeldung erhalten, als ich versucht habe, einen http-Datei-Upload manuell zu erstellen. Ich konnte ihn zum Laufen bringen, indem ich das Komma(,) durch ein Semikolon(;) in den Content-Type-Headern ersetzte. In Ihrem Fall durch Ersetzen von:

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

mit:

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

Dies scheint mit dem Python-Backend zusammenzuhängen, denn ich hatte dasselbe Problem mit Django(Python), und als ich es gegen einen PHP-Testserver testete, funktionierten sowohl Komma als auch Semikolon.

Schließlich ist das Beispiel in RFC1867 Verwenden Sie ein Komma, also bin ich mir nicht sicher, was wirklich die korrekte Vorgehensweise ist, aber das Semikolon hat das Problem für mich gelöst.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X