共用方式為


如何上傳檔案 (HTML)

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

這個主題將說明如何將資料或檔案從裝置上傳到網際網路。

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

對於大量、資料流方式或多部分傳輸 (視訊、音樂以及大型影像),其操作週期可能跨越多個應用程式暫停和 (或) 網路可用性變更,您的應用程式可以使用 Background Transfer

如需背景傳輸的高階資訊,請參閱在背景傳輸資料

先決條件

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

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

下列背景傳輸範例使用 JavaScript,並且使用背景傳輸範例做為依據。

背景傳輸上傳作業

使用背景傳輸時,上傳以 UploadOperation 的方式存在,可公開用於重新啟動或取消作業的一些控制方法。 系統會對每個 UploadOperation 自動處理應用程式事件 (例如暫停或終止) 和連線變更;在應用程式暫停期間上傳仍將繼續,或在應用程式終止之後會暫停或持續下去。此外,設定 CostPolicy 屬性將指出您的應用程式是否開始上傳,而且網際網路連線會使用計量付費網路。

以下的範例會逐步引導您建立和初始化基本上傳,以及如何列舉和重新引入之前應用程式工作階段中的持續作業。

上傳檔案

上傳的建立從 BackgroundUploader 開始。這個類別用來提供讓您的應用程式先設定上傳,再建立結果 UploadOperation 的方法。下列範例示範如何使用必要的 UriStorageFile 物件來執行這項操作。

  1. 識別上傳的檔案和目的地

    在開始建立 UploadOperation 之前,我們必須識別要上傳的目標位置 URI,以及要上傳的檔案。在下列範例中,填入 uriString 值的方式是使用 UI 輸入中的字串,而填入 file 值的方式則是使用 PickSingleFileAsync 操作傳回的 StorageFile 物件。

    function uploadFile() {
        var filePicker = new Windows.Storage.Pickers.FileOpenPicker();
        filePicker.fileTypeFilter.replaceAll(["*"]);
    
        filePicker.pickSingleFileAsync().then(function (file) {
            if (!file) {
                printLog("No file selected");
                return;
            }
    
            var upload = new UploadOp();
            var uriString = document.getElementById("serverAddressField").value;
            upload.start(uriString, file);
    
            // Store the upload operation in the uploadOps array.
            uploadOperations.push(upload);
        });
    }
    
  2. 建立和初始化上傳作業

    在上一個步驟中,uriStringfile 值已傳遞至我們下一個範例 UploadOp 的執行個體,這兩個值將被用來設定和啟動新的上傳操作。首先,會剖析 uriString 以建立必要的 Uri 物件。

    接下來,BackgroundUploader 會使用所提供之 StorageFile (file) 的屬性來填入要求標頭,並以 StorageFile 物件來設定 SourceFile 屬性。接著會呼叫 SetRequestHeader 方法,插入以字串方式提供的檔案名稱和 StorageFile.Name 屬性。

    最後,BackgroundUploader 會建立 UploadOperation (upload)。

    function UploadOp() {
        var upload = null;
        var promise = null;
    
        this.start = function (uriString, file) {
            try {
    
                var uri = new Windows.Foundation.Uri(uriString);
                var uploader = new Windows.Networking.BackgroundTransfer.BackgroundUploader();
    
                // Set a header, so the server can save the file (this is specific to the sample server).
                uploader.setRequestHeader("Filename", file.name);
    
                // Create a new upload operation.
                upload = uploader.createUpload(uri, file);
    
                // Start the upload and persist the promise to be able to cancel the upload.
                promise = upload.startAsync().then(complete, error, progress);
            } catch (err) {
                displayError(err);
            }
        };
        // On application activation, reassign callbacks for a upload
        // operation persisted from previous application state.
        this.load = function (loadedUpload) {
            try {
                upload = loadedUpload;
                promise = upload.attachAsync().then(complete, error, progress);
            } catch (err) {
                displayError(err);
            }
        };
    }
    

    請注意,非同步方法呼叫是使用 JavaScript Promise 定義的。看看上個範例的行:

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

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

上傳多個檔案

  1. 識別上傳的檔案和目的地

    在使用一個 UploadOperation 傳輸多個檔案的案例中,程序會照一般的方法開始,也就是先提供必要的目的地 URI 和本機檔案資訊。就像上一節的範例,使用者以字串提供 URI,而 FileOpenPicker 可以用來透過使用者介面指出檔案。不過,在這個案例中,應用程式應該改為呼叫 PickMultipleFilesAsync 方法,啟用透過 UI 選取多個檔案的功能。

    
    function uploadFiles() {
       var filePicker = new Windows.Storage.Pickers.FileOpenPicker();
       filePicker.fileTypeFilter.replaceAll(["*"]);
    
       filePicker.pickMultipleFilesAsync().then(function (files) {
          if (files === 0) {
             printLog("No file selected");
                return;
          }
    
          var upload = new UploadOperation();
          var uriString = document.getElementById("serverAddressField").value;
          upload.startMultipart(uriString, files);
    
          // Persist the upload operation in the global array.
          uploadOperations.push(upload);
       });
    }
    
  2. 針對提供的參數建立物件

    接下來的兩個範例使用單一範例方法 startMultipart 中的程式碼,並在上個步驟結束時呼叫它。為了清楚說明,已將建立 BackgroundTransferContentPart 物件陣列方法中的程式碼與建立結果 UploadOperation 的程式碼分開。

    首先,使用者提供的 URI 字串被初始化為 Uri。接下來,傳送給這個方法的 IStorageFile 物件陣列 (files) 會不斷重複,並使用每個物件來建立新的 BackgroundTransferContentPart 物件,然後放置在 contentParts 陣列中。

    
    upload.startMultipart = function (uriString, files) {
        try {
            var uri = new Windows.Foundation.Uri(uriString);
            var uploader = new Windows.Networking.BackgroundTransfer.BackgroundUploader();
    
            var contentParts = [];
            files.forEach(function (file, index) {
                var part = new Windows.Networking.BackgroundTransfer.BackgroundTransferContentPart("File" + index, file.name);
                part.setFile(file);
                contentParts.push(part);
            });
    
  3. 建立和初始化多部分上傳作業

    使用我們的 contentParts 陣列 (其中已填入代表每個要上傳的 IStorageFile 的所有 BackgroundTransferContentPart 物件),我們已準備好使用 Uri 來呼叫 CreateUploadAsync,以指示傳送要求的目的地。

            // Create a new upload operation.
            uploader.createUploadAsync(uri, contentParts).then(function (uploadOperation) {
    
               // Start the upload and persist the promise to be able to cancel the upload.
               upload = uploadOperation;
               promise = uploadOperation.startAsync().then(complete, error, progress);
            });
    
         } catch (err) {
             displayError(err);
         }
     };
    

在啟動時列舉持續作業

UploadOperation 完成或取消時,會釋放任何關聯的系統資源。不過,如果您的應用程式在這兩件事發生之前終止,就會暫停任何進行中的作業,而且仍會佔用與每個作業關聯的資源。如果這些操作沒有列舉且重新引回下一個應用程式工作階段,這些操作將不會完成,而且仍然會繼續佔用裝置資源。

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

    var uploadOperations = [];
    
  2. 接著我們要定義列舉持續作業的功能,然後將這些作業儲存在我們的陣列。 請注意,將回呼重新指派到 UploadOperation 時所呼叫的 load 方法 (應在應用程式終止期間都持續著),位於我們稍後在本節所定義的 UploadOp 類別中。

    function Windows.Networking.BackgroundTransfer.BackgroundUploader.getCurrentUploadsAsync() {
        .then(function (uploads) {
            for (var i = 0; i < uploads.size; i++) {
                var upload = new UploadOp();
                upload.load(uploads[i]);
                uploadOperations.push(upload);
            }
        }
    };
    

    注意  

    在 Windows Phone 市集應用程式中,當您的應用程式不在前景時,背景傳輸會持續進行。因為在此狀況下您的應用程式並未執行,所以傳輸完成時不會收到通知。當您的應用程式繼續時,如果您只檢查已完成傳輸的進度,狀態會是 BackgroundTransferStatus.Running。不過,當您連接到上述範例程式碼的傳輸時,會引發工作完成處理常式,也會更新傳輸狀態。

要求逾時

要考量的主要連線逾時情況有兩種:

  • 建立要傳輸的新連線時,如果在五分鐘內未建立連線要求,將會中止該要求。

  • 建立連線之後,將中止任何在兩分鐘內未收到回應的 HTTP 要求訊息。

注意  在任一種情況下,假設有網際網路連線,背景傳輸最多會自動重試要求三次。在偵測不到網際網路連線的事件中,其他要求將等到偵測到連線為止。

 

偵錯指導方針

在 Microsoft Visual Studio 中停止偵錯工作階段就等同於關閉應用程式;PUT 上傳會被暫停,POST 上傳會被終止。即使在偵錯時,應用程式應該列舉然後重新啟動或取消任何之前仍然存在的下載。例如,如果偵錯工作階段與之前的操作無關,您可以在應用程式啟動時,讓應用程式取消已列舉的持續上傳作業。

偵錯工作階段期間在應用程式啟動時列舉下載/上傳,如果該偵錯工作階段與之前的作業無關,您可以讓應用程式取消它們。請注意,如果有 Visual Studio 專案更新,像是變更應用程式資訊清單,而應用程式已解除安裝並重新部署,則 GetCurrentUploadsAsync 無法列舉使用前一個應用程式部署建立的作業。

如需詳細資訊,請參閱偵錯和測試 Windows 市集應用程式

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

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

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

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

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

摘要與後續步驟

在這個主題中,我們檢閱如何以 JavaScript 使用 Background Transfer API 來上傳檔案。

您也可以在 Windows 市集應用程式下載檔案。如需核心概念與範例說明,請參閱如何下載檔案

相關主題

其他

存取連線與數據傳輸方案資訊

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

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

如何設定網路功能

如何使用 WinJS.xhr 下載檔案

參考

BackgroundUploader

UploadOperation

Windows.Networking.BackgroundTransfer

範例

背景傳輸範例

HttpClient 範例

如何下載檔案

Windows.Networking.BackgroundTransfer

背景傳輸範例