Создать загрузку файлов, которые работают в IE

Я хочу написать файл загрузки script, который работает в IE, но два типа кода, который я пишу, имеют проблемы в IE.

Пожалуйста, помогите. Как вы можете написать файл загрузки script, который работает в IE?

Тип 1
Проблема Не поддерживает файл Api В IE (трюк не использовать его?)

    <!DOCTYPE html>

<html>
<head runat="server">
    <title></title>
    <script src="Scripts/jquery-1.6.2.js" type="text/javascript"></script>
    <script type="text/javascript">
        function updateSize() {
            var nBytes = 0;
            var nFiles=0;
            oFiles = document.getElementById("uploadInput").files;
            nFiles = oFiles.length;
            for (var nFileId = 0; nFileId < nFiles; nFileId++) {
                nBytes += oFiles[nFileId].size;
            }
            var sOutput = nBytes + " bytes";
            // optional code for multiples approximation
            for (var aMultiples = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"], nMultiple = 0, nApprox = nBytes / 1024; nApprox > 1; nApprox /= 1024, nMultiple++) {
                sOutput = nApprox.toFixed(3) + " " + aMultiples[nMultiple] + " (" + nBytes + " bytes)";
            }
            document.getElementById("fileNum").innerHTML = nFiles;
            document.getElementById("fileSize").innerHTML = sOutput;
        }
        // end of optional code
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <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>
</body>
</html>

Тип 2
Проблема не поддерживает document.getElementById('fileToUpload') .files [0] (Может ли трюк не получать файлы [0]?)

 <script src="Scripts/jquery-1.4.1.js" type="text/javascript"></script>
    <script type="text/javascript">
        function fileSelected() {
            var file = document.getElementById('fileToUpload').files[0];
            if (file) {
                var fileSize = 0;
                if (file.size > 1024 * 1024)
                    fileSize = (Math.round(file.size * 100 / (1024 * 1024)) / 100).toString() + 'MB';
                else
                    fileSize = (Math.round(file.size * 100 / 1024) / 100).toString() + 'KB';

                document.getElementById('fileName').innerHTML = 'Name: ' + file.name;
                document.getElementById('fileSize').innerHTML = 'Size: ' + fileSize;
                document.getElementById('fileType').innerHTML = 'Type: ' + file.type;
            }
        }

        function uploadFile() {
            var fd = new FormData();
            fd.append("fileToUpload", document.getElementById('fileToUpload').files[0]);
            var xhr = new XMLHttpRequest();
            xhr.upload.addEventListener("progress", uploadProgress, false);
            xhr.addEventListener("load", uploadComplete, false);
            xhr.addEventListener("error", uploadFailed, false);
            xhr.addEventListener("abort", uploadCanceled, false);
            $.post("UploadHandler.ashx");
            //xhr.open("POST", "UploadHandler.ashx");
            xhr.send(fd);
        }

        function uploadProgress(evt) {
            if (evt.lengthComputable) {
                var percentComplete = Math.round(evt.loaded * 100 / evt.total);
                document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';
                document.getElementById('prog').value = percentComplete;
            }
            else {
                document.getElementById('progressNumber').innerHTML = 'unable to compute';
            }
        }

        function uploadComplete(evt) {
            /* This event is raised when the server send back a response */
            alert(evt.target.responseText);
        }

        function uploadFailed(evt) {
            alert("There was an error attempting to upload the file.");
        }

        function uploadCanceled(evt) {
            alert("The upload has been canceled by the user or the browser dropped the connection.");
        }
    </script>

</head>
<body>
    <form id="form1">
    <div>
        <label for="fileToUpload">
            Select a File to Upload</label>
        <input type="file" name="fileToUpload[]" id="fileToUpload" onchange="fileSelected();" />
    </div>
    <div id="fileName">
    </div>
    <div id="fileSize">
    </div>
    <div id="fileType">
    </div>
    <div>
        <input type="button" onclick="uploadFile()" value="Upload" />
    </div>
    <div id="progressNumber">
    </div>
    <progress id="prog" value="0" max="100.0"></progress>
    </form>
</body>

Пожалуйста, помогите: (

Ответы

Ответ 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 - для синтаксического анализа загрузки. Возможно, вам будет легче настроить это, чем перевернуть свой собственный!

РЕДАКТИРОВАТЬ 2: Пренебрегать упоминанием проблем с событием iframe load. Исправлен ответ.