XMLHttpRequest POST multipart/form-data

Я хочу использовать XMLHttpRequest в JavaScript для POST формы, которая включает элемент ввода типа файла, чтобы я мог избежать обновления страницы и получить полезный XML обратно.

Я могу отправить форму без обновления страницы, используя JavaScript для установки целевого атрибута формы в iframe для MSIE или объект для Mozilla, но у этого есть две проблемы. Незначительная проблема заключается в том, что цель не соответствует W3C (поэтому я установил ее в JavaScript, а не в XHTML). Основная проблема заключается в том, что событие onload не срабатывает, по крайней мере, не в Mozilla на OS X Leopard. Кроме того, XMLHttpRequest улучшит код ответа, поскольку возвращаемые данные могут быть в формате XML, а не ограничиваться XHTML, как в случае с iframe.

Отправка формы приводит к HTTP, который выглядит так:

Content-Type: multipart/form-data;boundary=<boundary string>
Content-Length: <length>
--<boundary string>
Content-Disposition: form-data, name="<input element name>"

<input element value>
--<boundary string>
Content-Disposition: form-data, name=<input element name>"; filename="<input element value>"
Content-Type: application/octet-stream

<element body>

Как заставить метод отправки объекта XMLHttpRequest дублировать вышеуказанный поток HTTP?


person Robin like the bird    schedule 30.09.2008    source источник
comment
Вы приняли ответ через 9 лет! Вы второй с ним на stackexchange.   -  person peterh    schedule 24.03.2017


Ответы (7)


Вы можете создать запрос 'multipart/form-data' самостоятельно (подробнее об этом читайте на странице http://www.faqs.org/rfcs/rfc2388.html), а затем используйте метод send (т. е. xhr.send(your-multipart-form-data)). Аналогичным образом, но проще, в Firefox 4+ (также в Chrome 5+ и Safari 5+) вы можете использовать FormData, который помогает создавать такие запросы. Метод send хорош для текстового содержимого, но если вы хотите отправлять двоичные данные, такие как изображения, вы можете сделать это с помощью метода sendAsBinary, который использовался, начиная с Firefox 3.0. Подробнее о том, как отправлять файлы через XMLHttpRequest, см. на http://blog.igstan.ro/2009/01/pure-javascript-file-upload.html.

person Alex Polo    schedule 21.11.2010
comment
Святой ***. Спасибо! Пытался понять, как это сделать вручную в течение часа, когда мой сервер не смог разобрать то, что я отправил - person Romuald Brunet; 31.12.2017
comment
Было бы здорово иметь небольшое резюме того, что вы считаете важным в этих ссылках на случай, если серверы будут отключены. - person everyone; 14.08.2018

Нет никакого способа получить доступ к полю ввода файла внутри javascript, поэтому для загрузки файлов ajax не существует решения только для javascript.

Есть обходной путь, например использование iframe.

Другой вариант — использовать что-то вроде SWFUpload или Google Gears

person TonyB    schedule 30.09.2008

Я не понимаю, почему iframe (невидимый) подразумевает XHTML, а не ЛЮБОЙ контент. Если вы используете iframe, вы можете установить событие onreadystatechange и дождаться завершения. Затем вы можете использовать frame.window.document.innerHTML (пожалуйста, поправьте меня), чтобы получить результат строки.

var lFrame = document.getElementById('myframe');
lFrame.onreadystatechange = function()
{
   if (lFrame.readyState == 'complete')
   {
      // your frame is done, get the content...
   }
};
person helios    schedule 30.09.2008

Вам нужно будет выполнить POST в IFrame, чтобы заставить это работать, просто добавьте целевой атрибут в свою форму, где вы указываете идентификатор IFrame. Что-то вроде этого:


<form method="post" target="myiframe" action="handler.php">
...
</form>
<iframe id="myiframe" style="display:none" />

person mmattax    schedule 30.09.2008

я запутался в указанном вами событии загрузки, оно находится на странице или в iframe? первый ответ правильный, нет способа сделать это, используя только xmlhttprequest, если то, что вы хотите получить, запускает какой-то метод после того, как ответ существует в iframe просто проверьте, есть ли у него контент или нет, используя сценарии DOM, а затем запустите метод.

чтобы прикрепить событие загрузки к iframe

if(window.attachEvent){
 document.getElementById(iframe).attachEvent('onload', some_method);
}else{
 document.getElementById(iframe).addEventListener('load', some_method, false);
} 
person Komang    schedule 04.10.2008

Content-Disposition: данные формы, имя

Вы должны использовать точку с запятой, например: Content-Disposition: form-data; имя

person Aldekein    schedule 29.06.2011