Windows 8 提供 BackgroundDownloader 與 BackgroundUploader 類別,讓應用程式在暫停、終止甚至重啟後,仍能繼續下載/上傳大型檔案。本文詳細說明 API 用法、進度追蹤、暫停/繼續/取消控制,以及多檔案上傳技巧。
| 類別 | 用途 | 關鍵屬性/方法 |
|---|---|---|
| BackgroundDownloader | 管理下載任務 | CostPolicy, CreateDownload, GetCurrentDownloadsAsync |
| DownloadOperation | 單一下載作業 | Progress, StartAsync, AttachAsync, Pause, Resume, ResultFile |
| BackgroundUploader | 管理上傳任務 | CostPolicy, CreateUpload, CreateUploadAsync, GetCurrentUploadsAsync |
| UploadOperation | 單一上傳作業 | Progress, StartAsync, AttachAsync, SourceFile, GetResponseInformation |
var downloader = new BackgroundDownloader();
downloader.CostPolicy = BackgroundTransferCostPolicy.UnrestrictedOnly; // 允許計費網路
var download = downloader.CreateDownload(new Uri("https://example.com/largefile.zip"), destinationFile);
使用 Progress<DownloadOperation> 回報進度,並以 CancellationToken 控制取消:
var cts = new CancellationTokenSource();
var progress = new Progress<DownloadOperation>(op => {
var p = op.Progress;
model.Progress = $"{p.BytesReceived} / {p.TotalBytesToReceive} ({p.Status})";
});
await download.StartAsync().AsTask(cts.Token, progress);
var downloads = await BackgroundDownloader.GetCurrentDownloadsAsync();
foreach (var d in downloads) {
await HandleDownloadAsync(d, false); // false 表示非新任務,使用 AttachAsync
}
private async Task HandleDownloadAsync(DownloadOperation download, bool isNew) {
var model = new TransferModel { DownloadOperation = download };
_transfers.Add(model);
var progress = new Progress<DownloadOperation>(UpdateProgress);
if (isNew) await download.StartAsync().AsTask(_cts.Token, progress);
else await download.AttachAsync().AsTask(_cts.Token, progress);
}
// 暫停所有
foreach (var m in _transfers) m.DownloadOperation.Pause();
// 繼續所有
foreach (var m in _transfers) m.DownloadOperation.Resume();
// 取消所有
_cts.Cancel();
_cts = new CancellationTokenSource();
var uploader = new BackgroundUploader();
uploader.SetRequestHeader("Filename", "Logo.png");
var upload = uploader.CreateUpload(serverUri, sourceFile);
await HandleUploadAsync(upload, true);
var parts = new List<BackgroundTransferContentPart>();
for (int i=0; i<3; i++) {
var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/Logo.png"));
var part = new BackgroundTransferContentPart("File"+i, file.Name);
part.SetFile(file);
parts.Add(part);
}
var upload = await uploader.CreateUploadAsync(serverUri, parts);
await HandleUploadAsync(upload, true);
private async Task HandleUploadAsync(UploadOperation upload, bool isNew) {
var model = new TransferModel { UploadOperation = upload };
_transfers.Add(model);
var progress = new Progress<UploadOperation>(op => {
model.Progress = $"{op.Progress.BytesSent} / {op.Progress.TotalBytesToSend}";
});
if (isNew) await upload.StartAsync().AsTask(_cts.Token, progress);
else await upload.AttachAsync().AsTask(_cts.Token, progress);
// 上傳完成後取得回應
var resp = upload.GetResponseInformation();
model.Progress += $" | Status: {resp.StatusCode}";
}
ASP.NET WebForms UploadFile.aspx 同時支援單檔(透過 Header `Filename`)與多檔(Request.Files)接收:
protected void Page_Load(object sender, EventArgs e) {
if (Request.Headers["Filename"] != null) {
// 單檔
string fileName = Request.Headers["Filename"];
string path = Server.MapPath("UploadFiles") + "\\" + fileName.Insert(...);
using (var fs = new FileStream(path, FileMode.Create)) {
Request.InputStream.CopyTo(fs);
}
} else {
// 多檔
for (int i=0; i<Request.Files.Count; i++) {
var f = Request.Files[i];
if (f.ContentLength > 0) f.SaveAs(...);
}
}
}
Default:預設,不在計費網路(2G/3G/4G)傳輸。UnrestrictedOnly:允許計費網路,但不在漫遊時傳輸。Always:任何網路條件下皆傳輸(含漫遊),慎用。Background Transfer API 為大檔案傳輸提供了工業級的可靠性:自動斷點續傳、系統級排程、電源管理整合。搭配 TransferModel 封裝進度通知,即可構建流暢的使用者體驗。記得在 Manifest 宣告「背景傳輸」能力,並妥善處理 CostPolicy 以尊重使用者流量成本。