Dubrowsky
Хроники одного дупла
Блогово  →  WebDev  → 

Динамическая отправка формы с файлом в IE (ajax file upload + form.submit)

30 Октября 2013 года

Есть трюк, древний как мир. Называется "ajax file upload" и заключается в отправке файла на сервер без всякого аякса, а очень тупым способом, через динамически создаваемую форму и submit ее в iframe. Всегда работало, а тут сломалось. Ну, как сломалось, так и починилось, и писать не стоит, если бы не один фантастически смешной аспект поведения IE.

Итак, на дворе 2013 год, кругом HTML5, FileAPI и прочие чудеса техники. Это с одной стороны. А с другой - субмит в ифрейм и старый добрый ИЕ10 (на других не тестил).

Имеем нехитрый код:

// отправить поле file_input на сервер аяксом
function ajax_file_upload(file_input) {
	// создаем форму с target="ifr"
	var $f = 
		$('<form action="" method="post" target="ifr" enctype="multipart/form-data">'+
		'<input type="submit" />'+
		'</form>');
	// вставляем в нее input
	$f.append($(file_input));
	// вставляем форму в body
	$('body').append($f);
	// создаем ифрейм
	$('body').append('<iframe name="ifr" />');
	
	// отправляем форму
	var f = $f.get(0);
	f.submit();
}

Все предельно тупо. На самом деле это сокращенное содержание известной библиотечки jQuery AjaxFileUpload. Далее вешаем на change нашего <input type="file" /> вызов этой штуки и все ок.

Все ок, пока мы не решаем вместо уродливого инпута забабахать красивую кнопку. Дело привычное, инпут скрываем, а по клику на кнопке генерим клик по инпуту. Обработчики выглядят так:

// клик по кнопке
$('#coolbutton').click(function() {
	$('#fileinp').click();	
});

// выбор файла
$('#fileinp').change( function() {
	ajax_file_upload(this);
});

Везде работает, в ИЕ дохнет. Ностальжи )) Путем бубна и замысловатых ругательств заменяю последнюю строчку метода ajax_file_upload на вот такую конструкцию:

try {
	f.submit();
	console.log('submit 1 ok');
} catch (e) {
	console.log('submit 1 failed: '+e );
	try {
		f.submit();
		console.log('submit 2 ok');
	} catch (e2) {
		console.log('submit 2 failed: '+e2 );
		try {
			f.submit();
			console.log('submit 3 ok');
		} catch (e3) {
			console.log('submit 3 failed: '+e3 );
		}
	}
}

Идиотский код, не правда ли? Как вы думаете, что будет в консоли? А вот что:

submit 1 failed: Error: Отказано в доступе.
submit 2 failed: Error: Отказано в доступе.
submit 3 ok

Зрители аплодируют. Я великий хакер.

Кто-нибудь объяснит мне, что происходит?

Выкладываю полный кликабельный пример и его исходник. Расскажите, у кого какой результат в каком ИЕ? Там можно жать на инпут (тогда у меня срабатывает "subit 1 ok") и на ссылку (тогда с третьего раза, как выше).

Камменты

wasa30.10.2013, 22:39#
Ie 9 подтверждаю как в примере
vbb03.03.2014, 11:52#
ie запрещает в динамике указать значение для input[type="file"] и отправить его после этого в форме
Александр04.03.2014, 16:02#
Интересно
marin14.01.2016, 11:56#
спасибо, помог костыльчик ))

Написать коммент: памятка постеру

 

Крутые посты wtf??? →

15.02.2013 · 24 каммента · рейтинг 9.15
28.04.2008 · 44 каммента · рейтинг 9.12
23.01.2013 · 21 каммент · рейтинг 8.52
28.03.2008 · 24 каммента · рейтинг 6.71
19.01.2008 · 20 камментов · рейтинг 6.07

Последне камменты

24.09.2018  СаняТестовое задание для PHP-программиста (Junior): Хороший пример) А можно ради разнообразия аналогич...
31.07.2018  ДубрНаконец-то, нормальная работа с LESS в NetBeans: Sergio, вообще NetBeans кажется предлагал компилит...
18.07.2018  яндекс диск моя страницаНовый Яндекс.Браузер - браузер "Yandex" (отзыв / обзор): всем рекомендую
24.06.2018  SergioСвязь: Уважаемое автор. Прочитал статью про NetBeans и ...
21.06.2018  SergioНаконец-то, нормальная работа с LESS в NetBeans: Уважаемое "дупло"(автор). Как включить LESS в Net...

Статсы