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??? →

27.06.2012 · 37 камментов · рейтинг 12.31
15.02.2013 · 22 каммента · рейтинг 10.19
06.03.2008 · 29 камментов · рейтинг 7.92
28.03.2008 · 23 каммента · рейтинг 7.08
20.03.2014 · 7 камментов · рейтинг 6.68

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

18.04.2017  ДубрОбработка кликов и цели в Яндекс.Метрике, улучшенный вариант: Вячеслав, блин, я там скобку потерял =) Обновил, ...
17.04.2017  Вячеславтам же: вот http://www.totalat.ru/service/remont-akpp-bmw/
17.04.2017  Вячеславтам же: Вашу версию вставил. Даже alert проверочный вывод...
17.04.2017  Вячеславтам же: То что вы там запостили это вместо последнего куск...
17.04.2017  Дубртам же: Привет! 1) код лучше запостить куда-нибудь на ht...

Статсы