Ответ 1
Вы не можете использовать эти функции, если не используете IE10 или другой современный браузер. Обходные пути возможны для более ранних версий Internet Explorer (и других браузеров), но вам также нужно будет настроить свой внутренний код.
Почему это не работает
Internet Explorer до версии 10 не поддерживает ряд этих функций, ключевыми являются FormData и FileReader API. Оба фрагмента кода полагаются на API FileReader
, а второй также полагается на FormData
, чтобы загрузить файл динамически.
Как определить, выполнять ли код или нет
Недавно я написал виджет загрузки файлов, который обнаружил эти функции и обслуживал разные коды в зависимости от поддержки. Я использовал обнаружение функции из Modernizr, потому что тесты регулярно проверяются сообществом с открытым исходным кодом:
var support = {
// Are files exposed to JS?
// As used by Modernizr @
// https://github.com/Modernizr/Modernizr/blob/master/feature-detects/file/api.js
'fileReader' : (function testFileReader(){
// Test: look for global file class.
return !!(window.File && window.FileList && window.FileReader);
}()),
// AJAX file upload via formData?
'formData' : window.FormData !== void 0
};
Для вашей функции fileSelected
вам понадобится support.fileReader
для оценки true
; для uploadFile
вам нужно support.formData
.
Обходной путь для браузеров, которые не поддерживают эти функции
Без этих функций невозможно прочитать файл с внешнего интерфейса или отправить файл с помощью AJAX. Однако вы можете отправить свой файл с помощью скрытого <iframe/>
внутри вашей текущей страницы и получить UploadHandler.ashx
, чтобы иначе реагировать на запросы, отличные от XHR.
Это решение технически синхронно (просто происходит на другой скрытой странице), поэтому вы не получите обновлений - единственная обратная связь - это когда загрузка завершена и сервер ответил. Таким образом, вы сможете только сообщать пользователю о имени файла, его размере и успехе после того, как они полностью загрузили его, что может занять некоторое время!
В любом случае HTML для этого будет выглядеть следующим образом:
<form
id="form1"
runat="server"
action="UploadHandler.ashx"
target="fileIframe">
<iframe
name="fileIframe"
style="display:none"
onload="parseIframeResponse"
tabindex="-1">
</iframe>
<p>
<input id="uploadInput" type="file" name="myFiles" onchange="updateSize();" multiple />
selected files:
<span id="fileNum">
0
</span>
; total size:
<span id="fileSize">
0
</span>
</p>
<p>
<input type="submit" value="Send file">
</p>
</form>
Несколько изменений:
- Теперь форма имеет
target
, что означает, что когда он отправляет свой контент в URI вaction
, он будет загружать ответ там, в отличие от текущей страницы. - Цель - ссылка
name
на iframe, который мы включили. Он скрыт с помощьюdisplay:none
и задан отрицательныйtabindex
, чтобы убедиться, что пользователь не наткнулся на него. Он также имеет свойствоonload
. Это единственный способ привязки функций к событию загрузки в более старых версиях IE.
Итак, когда форма отправлена, мы остаемся на текущей странице, а ответ сервера загружается в нашем скрытом iframe. Когда это произойдет, браузер выполнит функцию, названную в атрибуте onload
. К сожалению, это означает, что функция должна находиться в глобальном масштабе!
Базовый компонент
Я не знаю, как работает ваш back-end, но если iframe загружает ответ вместо его загрузки, он должен быть HTML или обычным текстом (и это нужно будет указать в mime- тип). Вы можете узнать, была ли форма размещена через AJAX из внешнего сервера, ища заголовок X-Requested-With
, который должен иметь значение XMLHttpRequest
- если этого не существует, iframe запрашивает ответ и вам нужно отправить текст или HTML. Возможно, вы захотите выровнять ответ JSON, который предоставляет значения, которые вы хотели бы вернуть пользователю, например fileName
, fileSize
и fileType
. Я надеюсь, что вы сами это сделаете или попросите коллегу справиться с этим.
Захват ответа iframe
Как уже упоминалось, функция обработчика ответа должна находиться в глобальной области действия для атрибута onload
для привязки к нему из-за того, что старый IE очень изворотливый. Я вижу, что вы используете jQuery, поэтому, если вы спустили маршрут навязывания ответа сервера, вы можете записать эту функцию следующим образом:
function parseIframeResponse(){
var response = $('#fileIframe').contents().find('body').text();
var object = $.parseJSON(response);
}
Проблемы с привязкой события iframe
load
Как упоминалось ранее, событие загрузки iframe должно быть привязано inline как атрибут самого iframe - это потому, что IE просто не сможет зарегистрировать его в противном случае. Но это само по себе само по себе, потому что даже пустой iframe (пустой или не существующий
src
по умолчанию равенabout:blank
) запускает событие загрузки. Чтобы смягчить это, вам нужно будет отбросить любойresponse
, который оценивает пустую строку как ложное положительное, и убедитесь, что ваш back-end отвечает некоторым контентом, даже если он встречает ошибку.
Предположительно, вам нужно будет использовать любую информацию, чтобы выполнить часть кода, который вы получили в настоящее время в функциях fileSelected
, uploadProgress
и т.д.
Надеюсь, что это поможет.
EDIT 1: готовые решения
Оглядываясь назад, несмотря на то, что, написав это с того момента, как я разработал свое собственное решение проблемы, можно было считать небрежным, не говоря уже о Fine Uploader, сильно протестированный (более 700 закрытых выпусков!) и поддерживаемый автономный плагин, целью которого является достижение наилучшего возможного загрузки файлов для IE7 и вверх. Там также хороший выбор серверных компонентов - включая ASP.NET - для синтаксического анализа загрузки. Возможно, вам будет легче настроить это, чем перевернуть свой собственный!