Как скачать файл (HTML)

[ Эта статья адресована разработчикам приложений среды выполнения Windows для Windows 8.x и Windows Phone 8.x. При разработке приложений для Windows 10 см. раздел последняя документация]

В этой теме описывается процедура скачивания файла.

Приложения могут использовать описанные в этом разделе API, чтобы обеспечить взаимодействие с веб-службами для потребления или совместного использования распространенных форматов мультимедиа, таких как фотографии, музыка и видео.

При разработке приложения на JavaScript для запроса файлов из расположения в Интернете используются два основных способа. Небольшие файлы, например часто запрашиваемые материалы сайта, можно скачивать с помощью функции XHR для получения асинхронного HTTP-запроса GET. Эта функция представляет вызов XMLHttpRequest в виде объекта Promise, программного шаблона, с помощью которого в JavaScript реализуется асинхронное поведение.

Либо, чтобы предоставить согласованное взаимодействие при скачивании больших файлов мультимедиа (видео и музыка), которое может длиться в течение нескольких рабочих циклов приложения или при различных режимах доступности сети, приложение может использовать Background Transfer. Подробнее: Передача данных в фоновом режиме.

Необходимые условия

Общие рекомендации по созданию приложения на JavaScript см. в разделе Создание первого приложения среды выполнения Windows на JavaScript. Для завершения асинхронных операций в этом разделе также используются объекты Promise в JavaScript. Подробнее об этой технике программирования: Асинхронное программирование на JavaScript с использованием объектов Promise.

Чтобы подготовить приложение для работы в сети, необходимо настроить такую возможность в файле проекта Package.appxmanifest. Определение всех сетевых возможностей см. в разделе о настройке возможностей сетевой изоляции.

Все примеры фоновой передачи в этом разделе основаны на образце передачи данных в фоновом режиме.

Загрузка файла с помощью XHR

Чтобы инициировать обычный асинхронный HTTP-запрос с помощью JavaScript, следует вызвать XHR и указать релевантные данные запроса в параметре Option. По умолчанию вызов этого метода — это запрос GET, поэтому единственными значениями, которые необходимо указать в параметре Option, являются URL-адрес и responseType. Однако многие веб-службы требуют проверки подлинности, и при запросе ресурсов из такой защищенной веб-службы вызов XHR должен содержать эти учетные данные.

Для выполнения операции GET XHR также требуется, чтобы тип ожидаемого в ответе содержимого был указан с помощью responseType в параметре Option. В нашем примере мы запросили PNG-файл, поэтому responseType будет иметь значение "BLOB". Полный список поддерживаемых типов содержимого и примеры их запросов см. в разделе Как скачать файл с помощью WinJS XHR.


WinJS.xhr({ url: "https://www.microsoft.com/windows/Framework/images/win_logo.png", responseType: "blob" })
    .done(
        function (request) {
            var imageBlob = URL.createObjectURL(request.response);
            var imageTag = xhrDiv.appendChild(document.createElement("image"));
      imageTag.src = imageBlob;
     });

В JavaScript каждый объект Promise имеет две функции, которые вы можете использовать для обработки результатов асинхронной операции, — then и done. Обе функции принимают три параметра: функцию, которая вызывается по окончании скачивания (то есть когда readyState равно 4); функцию, которая вызывается в случае ошибки; и функцию, которая вызывается в ходе скачивания (то есть когда readyState равно 2 или 3). Только функция done выдает исключение, если ошибка не обработана. Если функция ошибки не предусмотрена, предпочтительно использовать эту функцию.

Скачивание файла с помощью функции передачи данных в фоновом режиме

При использовании функции передачи данных в фоновом режиме каждая загрузка происходит в DownloadOperation, который обеспечивает доступ к методам управления, позволяющим приостанавливать, возобновлять, перезапускать и отменять операцию. События приложения (например, приостановка или завершение работы) и изменения сетевого подключения обрабатываются системой автоматически в соответствии с DownloadOperation. Скачивание будет продолжаться в периоды приостановки приложения либо будет приостанавливаться и сохраняться в случаях завершения работы приложения. Для мобильных сетевых сценариев можно установить свойство CostPolicy, которое определяет, будет ли ваше приложение начинать или продолжать скачивание, если подключение к Интернету осуществляется через сеть с лимитным тарифным планом.

В следующих примерах будет показано, как создать и инициализировать простое скачивание, а также как перечислить и воспроизвести операции, сохраненные в предыдущем сеансе приложения.

Hh700370.wedge(ru-ru,WIN.10).gifНастройка и запуск фонового скачивания файла

  • В следующем примере демонстрируется способ использования строк, представляющих универсальный код ресурса (URI), и имени файла для создания объекта Uri и класса StorageFile, в который будет помещен запрошенный файл. В этом примере новый файл автоматически помещается в заранее определенное расположение. В качестве альтернативы можно использовать FileSavePicker, это даст пользователям возможность указать расположение для сохранения файла на устройстве. Обратите внимание, что метод load, вызываемый для переназначения обратных вызовов для операции DownloadOperation, если она сохраняется при завершении работы приложения, содержится в классе DownloadOp, который будет определен ниже в этом разделе.

    function DownloadOp() {
        var download = null;
        var promise = null;
        var imageStream = null;
    
        this.start = function (uriString, fileName) {
            try {
                // Asynchronously create the file in the pictures folder.
                Windows.Storage.KnownFolders.picturesLibrary.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.generateUniqueName).done(function (newFile) {
                    var uri = Windows.Foundation.Uri(uriString);
                    var downloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader();
    
                    // Create a new download operation.
                    download = downloader.createDownload(uri, newFile);
    
                    // Start the download and persist the promise to be able to cancel the download.
                    promise = download.startAsync().then(complete, error, progress);
                }, error);
            } catch (err) {
                displayException(err);
            }
        };
        // On application activation, reassign callbacks for a download
        // operation persisted from previous application state.
        this.load = function (loadedDownload) {
            try {
                download = loadedDownload;
                printLog("Found download: " + download.guid + " from previous application run.<br\>");
                promise = download.attachAsync().then(complete, error, progress);
            } catch (err) {
                displayException(err);
            }
        };
    }
    

    Обратите внимание на асинхронные вызовы метода, определенные при помощи объектов Promise на JavaScript. См. строку 17 предыдущего примера кода:

    promise = download.startAsync().then(complete, error, progress);
    

    За вызовом асинхронного метода следует оператор "then", указывающий определенные приложением методы, которые вызываются при возврате результата из асинхронного метода. Подробнее об этой технике программирования: Асинхронное программирование на JavaScript с использованием объектов Promise.

Hh700370.wedge(ru-ru,WIN.10).gifДобавление дополнительных методов управления работой

  • Уровень управления может быть повышен с помощью реализации дополнительных методов DownloadOperation. Так, чтобы обеспечить возможность отменять операцию, можно добавить в пример выше следующий код.

    // Cancel download.
    this.cancel = function () {
        try {
            if (promise) {
                promise.cancel();
                promise = null;
                printLog("Canceling download: " + download.guid + "<br\>");
                if (imageStream) {
                    imageStream.close();
                }
            }
            else {
                printLog("Download " + download.guid + " already canceled.<br\>");
            }
        } catch (err) {
            displayException(err);
        }
    };
    

После завершения или отмены DownloadOperation все связанные системные ресурсы освобождаются. Однако если приложение завершает работу до того, как происходит одно из этих событий, скачивание будет приостановлено и сохранено в фоновом режиме. В следующих примерах показано, как воспроизвести приостановленное скачивание в новом сеансе приложения.

Hh700370.wedge(ru-ru,WIN.10).gifПеречисление сохраненных операций при запуске

  1. Перед тем как определить функцию, перечисляющую сохраненные операции, нам нужно создать массив, который будет содержать объекты DownloadOperation, возвращенные этой функцией.

    var downloadOps = [];
    
  2. Затем определяем функцию, которая перечисляет сохраненные операции и сохраняет их в нашем массиве. Обратите внимание, что метод load, вызываемый для переназначения обратных вызовов для сохраненной операции DownloadOperation, содержится в примере DownloadOp, который будет определен ниже в этом разделе.

    // Enumerate outstanding downloads.
    Windows.Networking.BackgroundTransfer.BackgroundDownloader.getCurrentDownloadsAsync().done(function (downloads) {
    
        for (var i = 0; i < downloads.size; i++) {
            var download = new DownloadOp();
            download.load(downloads[i]);
            downloadOps.push(download);
        }
    });
    

    Примечание  

    Для универсальных приложений Windows Phone передачи данных в фоновом режиме продолжаются, когда приложение находится не на переднем плане. Поскольку приложение в этом сценарии не выполняется, оно не получает уведомления при завершении передачи. Если при возобновлении работы приложения проверить ход выполнения завершенной передачи данных, его состояние будет BackgroundTransferStatus.Running. Тем не менее при подключении к передаче, как показано в примере кода выше, обработчик выполнения задач будет вызван и состояние передачи будет обновлено.

Тайм-ауты запросов

Таким образом, следует учитывать два основных сценария тайм-аута подключения.

  • При отсутствии ответа на запрос нового подключения для передачи в течение пяти минут такой запрос отменяется.

  • Если подключение установлено, любой HTTP-запрос отменяется при отсутствии ответа в течение двух минут.

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

Для операций XHR может быть установлено определенное время ожидания с использованием свойства WinJS.Promise.timeout. Подробнее об этом см. в разделе Установка значений тайм-аута с помощью WinJS.xhr.

Рекомендации по отладке

Остановка сеанса отладки в Microsoft Visual Studio сопоставима с закрытием приложения. Даже во время отладки ваше приложение должно перечислить, а затем возобновить, перезапустить или отменить все операции скачивания, продолжающиеся с предыдущего сеанса. Например, можно настроить приложение для отмены продолжающихся перечисленных операций скачивания при запуске приложения, если предыдущие операции не представляют интереса для текущего сеанса отладки.

Если имели место обновления проекта Visual Studio, например изменения в манифесте приложения, а приложение было удалено и развернуто повторно, GetCurrentUploadsAsync не может перечислить операции, инициированные с использованием предыдущего развертывания приложения.

Дополнительную информацию см. в разделе Отладка и тестирование приложений Магазина Windows с помощью Visual Studio.

Если при развертывании вы используете фоновую передачу данных, синхронизация внутреннего кэша активных и завершенных операций передачи может быть нарушена. В результате этого запуск новой операции передачи или взаимодействие с существующими операциями и объектами BackgroundTransferGroup может стать невозможным. В ряде случаев попытка взаимодействия с существующими операциями способна вызвать сбой. Это может произойти, если свойство TransferBehavior задано как Parallel. Такая проблема присуща определенным сценариям во время разработки и не затрагивает конечных пользователей приложения.

Проблема может возникнуть в четырех сценариях с использованием Visual Studio:

  • если вы создаете новый проект с таким же именем приложения, как в существующем проекте, но на другом языке (например, не C++, а C#);
  • если вы изменяете архитектуру конечного объекта (например, с x86 на x64) в существующем проекте;
  • если вы изменяете культуру (например, с нейтральной на en-US) в существующем проекте;
  • если вы добавляете или удаляете возможность в манифесте пакета (например, добавляете корпоративную аутентификацию) в существующем проекте.

Обычное обслуживание приложения, включая обновления манифеста, добавляющие или удаляющие возможности, не вызывает данную проблему при развертывании приложения у конечных пользователей.

Чтобы обойти проблему, полностью удалите все версии приложения и повторите развертывание с новым языком, архитектурой, культурой или возможностью. Для этого можно использовать начальный экран или PowerShell и командлет Remove-AppxPackage.

Краткая сводка и дальнейшие действия

В этой теме мы рассмотрели процедуру загрузки файлов с помощью API Background Transfer в JavaScript. Мы узнали, в чем между ними разница, и выявили зависимость их практического применения от размера и времени скачивания файла.

Кроме того, вы можете использовать XHR и передачу данных в фоновом режиме для выкладывания файлов. Описание основных принципов работы и примеры см. в разделе о том, как отправить файл.

Связанные разделы

Прочие ссылки

Асинхронное программирование на JavaScript с использованием объектов Promise

Создание первого приложения среды выполнения Windows на JavaScript

Как настроить возможности сети

Как скачать файл с помощью WinJS XHR

Как отправить файл

Ссылки

HttpClient

Windows.Networking.BackgroundTransfer

WinJS.XHR

Примеры

Пример Background Transfer

Пример HttpClient