共用方式為


如何下載檔案 (HTML)

[ 本文的目標對象是撰寫 Windows 執行階段 App 的 Windows 8.x 和 Windows Phone 8.x 開發人員。如果您正在開發適用於 Windows 10 的 App,請參閱 最新文件 ]

這個主題將說明如何下載檔案。

應用程式可以使用本主題討論的 API,讓這些應用程式能夠與 Web 服務互動,以使用或分享普遍使用的媒體格式,如相片、音樂及影片。

使用 JavaScript 開發應用程式時,有兩個主要選項用來要求網際網路位置上的檔案。小型檔案 (像是經常擷取的網站資產) 可以使用 XHR 進行非同步 HTTP GET 要求來下載。這個函式會在 Promise 中包裝 XMLHttpRequest 呼叫,Promise 是一種程式設計模式,允許 JavaScript 的非同步行為。

或者,為了在下載較大型媒體 (影片和音樂) 時提供一致體驗,其操作週期可能跨越多個應用程式暫停和 (或) 網路可用性變更,您的應用程式可以使用 Background Transfer。如需背景傳輸的高階資訊,請參閱在背景傳輸資料

先決條件

如需建立 JavaScript 應用程式的一般協助,請參閱使用 JavaScript 建立您的第一個 Windows 執行階段應用程式。另外,這個主題中使用 JavaScript Promise 來完成非同步操作。如需這種程式設計模式的詳細資訊,請參閱使用 Promise 在 JavaScript 的非同步程式設計

若要確保應用程式的網路可正常運作,您必須在專案 Package.appxmanifest 檔案中設定功能。 如需每個網路功能的定義,請參閱如何設定網路隔離功能

本主題中的所有背景傳輸範例使用背景傳輸範例做為依據。

使用 XHR 下載檔案

若要使用 JavaScript 起始基本的非同步 HTTP 要求,請呼叫 XHR 並使用 Option 參數將相關的要求資料提供給它。根據預設,這個方法呼叫是一種 GET 要求,因此透過 Option 提供的唯一必要值是 URL 和 responseType。不過,許多 Web 服務都需要驗證,而且當呼叫 XHR 從任何安全的 Web 服務要求資源時,應該包括這些認證。

XHR GET 操作也需要使用 Option 參數中的 responseType 來指定回應中所需的內容類型。在範例中,我們要求 .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(zh-tw,WIN.10).gif設定和啟動背景傳輸檔案下載

  • 下列範例示範代表 URI 和檔案名稱的字串如何可以用來建立 Uri 物件,以及將包含所要求檔案的 StorageFile。在這個範例中,會自動將新檔案放在預先定義的位置。 或者,您可以使用 FileSavePicker 讓使用者指出將檔案儲存在裝置上的哪個位置。請注意,將回呼重新指派到 DownloadOperation 時所呼叫的 load 方法 (應於應用程式終止期間都持續著),位於稍後在本節所定義的 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);
            }
        };
    }
    

    請注意,非同步方法呼叫是使用 JavaScript Promise 定義的。請查看前面程式碼範例的第 17 行:

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

    非同步呼叫後面跟著一個指示方法的 then 陳述式,由應用程式定義,會在非同步方法呼叫傳回結果時呼叫它。如需這種程式設計模式的詳細資訊,請參閱使用 Promise 在 JavaScript 的非同步程式設計

Hh700370.wedge(zh-tw,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(zh-tw,WIN.10).gif在啟動時列舉持續作業

  1. 在定義列舉持續作業的功能之前,我們必須建立一個陣列來包含其將傳回的 DownloadOperation 物件:

    var downloadOps = [];
    
  2. 接著我們要定義列舉持續作業的功能,然後將這些作業儲存在我們的陣列。 請注意,重新指派回呼以進行持續 DownloadOperation 時所呼叫的 load 方法,位於我們稍後在本節所定義的 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 市集應用程式

開發期間使用背景傳送時,您可能會面臨使用中及已完成傳送作業的內部快取不同步的情況。這會導致無法開始新的傳送作業或無法與現有的作業和 BackgroundTransferGroup 物件互動。在某些情況下,嘗試與現有作業互動會造成當機。如果 TransferBehavior 屬性設為 Parallel,就會發生這種結果。這個問題只在開發期間的特定情況下發生,不適用於您應用程式的一般使用者。

使用 Visual Studio 時有四種情況會導致這個問題。

  • 您使用與現有專案相同的名稱但不同的語言 (例如,從 C++ 變更為 C#) 建立新的專案。
  • 您變更現有專案中的目標架構 (例如,從 x86 變更為 x64)。
  • 您變更現有專案中的文化特性 (例如,從中性變更為 en-US)。
  • 您在現有專案的套件資訊清單中新增或移除功能 (例如,新增 [企業驗證])。

一般應用程式服務,包括新增或移除功能的資訊清單更新,並不會在應用程式的一般使用者部署上引起這個問題。

若要解決這個問題,請完整解除安裝應用程式的所有版本,然後使用新的語言、架構、文化特性或功能來重新部署。這個操作可以透過 [開始]**** 畫面或使用 PowerShell 和 Remove-AppxPackage Cmdlet 來完成。

摘要與後續步驟

在這個主題中,我們已檢閱如何以 JavaScript 使用 Background Transfer API 來下載檔案。我們也檢閱了兩者的差異,並特別強調實際應用如何依存於檔案下載的大小和生命週期。

您也可以使用 XHR 和背景傳輸上傳檔案。如需核心概念與範例說明,請參閱如何上傳檔案

相關主題

其他

使用 Promise 在 JavaScript 的非同步程式設計

使用 JavaScript 建立您的第一個 Windows 執行階段應用程式

如何設定網路功能

如何使用 WinJS.xhr 下載檔案

如何上傳檔案

參考

HttpClient

Windows.Networking.BackgroundTransfer

WinJS.XHR

範例

背景傳輸範例

HttpClient 範例