Я пытаюсь создать данные Multipart Form непосредственно в Javascript для отправки моих данных на сервер. Я знаю, что есть плагины форм Ajax, но я действительно думаю, что они не удовлетворят моим потребностям, так как я буду создавать двоичные данные в браузере и отправлять их, как если бы это был файл, отправляемый (сервер, на котором я буду публиковать, требует этого). 1001 *
Моя проблема заключается в том, что самый простой пример построения текстовых данных MIME Multipart завершается с ошибкой на стороне сервера:
500 Internal Server Error: Invalid boundary in multipart form
Я попытался свести код к минимуму: в этом файле main.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, который поступает на сервер при использовании формы:
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--
А это объект Request, поступающий на сервер при использовании функции 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» извлекает значение «содержимого», отправленного браузером, и сохраняет его в глобальной переменной. После этого при вызове «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