How to upload a file (XAML)
This topic will show you how to upload data or a file from a device to the Internet.
Apps can use the APIs discussed in this topic to enable their app to interact with web services to consume or share popular media formats like photos, music, and video.
For large, stream-based, or multi-part uploads (video, music, and large images), with an operational lifetime that may span beyond multiple app suspensions and/or changes in network availability, your app can use Background Transfer.
For a high-level look at Background Transfer, see Transferring data in the background.
Prerequisites
For general help creating a C#/C++ Windows Runtime app, see Create your first Windows Runtime app using C# or Visual Basic.
To ensure your app is network ready, you must set the capability in the project Package.appxmanifest file. For a definition of each network capability, see How to configure network isolation capabilities.
The following Background Transfer examples use C# and are based on the Background Transfer sample.
Background Transfer Upload Operations
When using Background Transfer an upload exists as an UploadOperation that exposes a number of control methods that are used to restart or cancel the operation. App suspension and connectivity changes are compensated for automatically; uploads will continue during app suspension periods, UploadOperations persist through app termination so that aborted uploads can be retried. For mobile network scenarios CostPolicy values can be set per operation to indicate whether or not your app will conduct an upload while a metered network is being used for Internet connectivity.
The following examples will walk you through the creation and initialization of a basic upload and how to enumerate and reintroduce operations persisted from a previous app session.
Namespace declarations
The following Windows Runtime and .NET namespaces are referenced in this topic.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Networking.BackgroundTransfer;
using Windows.Storage.Pickers;
using Windows.Storage;
Upload a file
The creation of an upload begins with BackgroundUploader. This class is used to provide the methods that enable your app to configure the upload before creating the resultant UploadOperation. The following example shows how to do this with the required Uri and StorageFile objects.
Identify the file and destination for the upload
Before we can begin with the creation of an UploadOperation, we first need to identify the URI that indicates the location to upload to, and the file that will be uploaded. In the following example, a Uri is defined using a string value provided via a UI input field, and the desired file for upload, represented by a StorageFile object, is returned when the end-user has selected a file through the UI provided by the PickSingleFileAsync operation.
Uri uri = new Uri(serverAddressField.Text.Trim()); FileOpenPicker picker = new FileOpenPicker(); picker.FileTypeFilter.Add("*"); StorageFile file = await picker.PickSingleFileAsync();
Create the upload operation
The Uri and StorageFile objects are then passed to an instance of BackgroundUploader, where they can be used to configure and create our upload.
First, the properties of the provided StorageFile are used by BackgroundUploader to populate the request header and set the SourceFile property with the StorageFile object. The SetRequestHeader method is then called to insert the file name, provided as a string, and the StorageFile.Name property values into the header for the upload request.
With the operation details configured, BackgroundUploader creates the UploadOperation (upload), which is then passed to our HandleUploadAsync method to attach a progress handlers and start the upload.
BackgroundUploader uploader = new BackgroundUploader(); uploader.SetRequestHeader("Filename", file.Name); UploadOperation upload = uploader.CreateUpload(uri, file); // Attach progress and completion handlers. await HandleUploadAsync(upload, true);
Configure an upload for multiple files
Identify the files and destination for the upload
In a scenario involving multiple files transferred with a single UploadOperation, the process begins as it usually does by first providing the required destination URI and local file information. Like our earlier example, the URI is provided as a string by the end-user through the UI and FileOpenPicker can again be used to indicate files. However, in a multiple file upload scenario the app should instead call the PickMultipleFilesAsync method to enable the selection of multiple files through a UI.
Uri uri = new Uri(serverAddressField.Text.Trim()); FileOpenPicker picker = new FileOpenPicker(); picker.FileTypeFilter.Add("*"); IReadOnlyList<StorageFile> files = await picker.PickMultipleFilesAsync();
Create objects for the provided parameters
The next two examples use code contained in a single example method, startMultipart, which was called at the end of the last step. For the purpose of instruction the code in the method that creates an array of BackgroundTransferContentPart objects has been split from the code that creates the resultant UploadOperation.
The list of StorageFile objects (files) returned by PickMultipleFilesAsync is passed to the following example code, where it is iterated through and each object is used to create a new BackgroundTransferContentPart object. All resultant BackgroundTransferContentPart are then added to a new list defined as parts.
List<BackgroundTransferContentPart> parts = new List<BackgroundTransferContentPart>(); for (int i = 0; i < files.Count; i++) { BackgroundTransferContentPart part = new BackgroundTransferContentPart("File" + i, files[i].Name); part.SetFile(files[i]); parts.Add(part); }
Create the upload operation
With all files represented as BackgroundTransferContentPart objects in the parts list, we are ready to call CreateUploadAsync, using the Uri to indicate where the request will be sent.
BackgroundUploader uploader = new BackgroundUploader(); UploadOperation upload = await uploader.CreateUploadAsync(uri, parts); // Attach progress and completion handlers. await HandleUploadAsync(upload, true);
Attaching progress handlers and starting our upload
In this topic we enumerated persisted, or created new, uploads that were then passed to a custom async HandleUploadAsync task to attach app defined progress and completion handlers when starting the transfer request. The following code defines this task.
private async Task HandleUploadAsync(UploadOperation upload, bool start)
{
try
{
Progress<UploadOperation> progressCallback = new Progress<UploadOperation>(UploadProgress);
if (start)
{
// Start the upload and attach a progress handler.
await upload.StartAsync().AsTask(cts.Token, progressCallback);
}
else
{
// The upload was already running when the application started, re-attach the progress handler.
await upload.AttachAsync().AsTask(cts.Token, progressCallback);
}
ResponseInformation response = upload.GetResponseInformation();
Log(String.Format("Completed: {0}, Status Code: {1}", upload.Guid, response.StatusCode));
}
catch (TaskCanceledException)
{
Log("Upload cancelled.");
}
catch (Exception ex)
{
LogException("Error", ex);
}
}
Note There are methods referred to in this example that define app behavior depending on the current progress of an upload. For examples of this behavior, download the Background Transfer sample.
Enumerate persisted operations at start-up
On completion or cancellation of an UploadOperation, any associated system resources are released. However, if your app is terminated before either of these things can occur, the active transfer is aborted, but the UploadOperation associated with it remains for use in the next app session.
It's the ability for Background Transfer operations to persist through app termination that adds a new, and simple, best practice; enumerate all existing UploadOperation instances at app start-up. If operations are not enumerated and re-introduced to the current Background Transfer process, they will go stale and continue to occupy device resources.
The following code enumerates all UploadOperation and iterates through the list, calling HandleDownloadAsync, a method defined later in this topic, to re-attach progress and completion handlers. This enumeration task only needs to be carried out at the beginning of an app session, as only app terminations during active transfers introduce this scenario.
IReadOnlyList<UploadOperation> uploads = await BackgroundUploader.GetCurrentUploadsAsync(); if (uploads.Count > 0) { List<Task> tasks = new List<Task>(); foreach (UploadOperation upload in uploads) { // Attach progress and completion handlers. tasks.Add(HandleUploadAsync(upload, false)); } await Task.WhenAll(tasks); } }
Note
For Windows Phone Store apps, background transfers continue to progress while your app is not in the foreground. Because your app is not running in this scenario, it will not receive a notification when the transfer completes. When your app resumes, if you just check the progress of a completed transfer, the status will be BackgroundTransferStatus.Running. However, when you attach to the transfer as in the example code above, the task completion handler will be raised and the transfer status will be updated.
Next we'll demonstrate the creation and configuration of upload operations for a single file, or multiple files.
Request Timeouts
There are two primary connection timeout scenarios to take into consideration:
When establishing a new connection for a transfer, the connection request is aborted if it is not established within five minutes.
After a connection has been established, an HTTP request message that has not received a response within two minutes is aborted.
Note In either scenario, assuming there is Internet connectivity, Background Transfer will retry a request up to three times automatically. In the event Internet connectivity is not detected, additional requests will wait until it is.
Debugging Guidance
Stopping a debugging session in Microsoft Visual Studio is comparable to closing your app; PUT uploads are paused and POST uploads are terminated. Even while debugging, your app should enumerate and then restart or cancel any persisted uploads. For example, you can have your app cancel enumerated persisted upload operations at app startup if there is no interest in previous operations for that debug session.
While enumerating downloads/uploads on app startup during a debug session, you can have your app cancel them if there is no interest in previous operations for that debug session. Note that if there are Visual Studio project updates, like changes to the app manifest, and the app is uninstalled and re-deployed, GetCurrentUploadsAsync cannot enumerate operations created using the previous app deployment.
See Debugging and testing Windows Store apps for more information.
When using Background Transfer during development, you may get into a situation where the internal caches of active and completed transfer operations can get out of sync. This may result in the inability to start new transfer operations or interact with existing operations and BackgroundTransferGroup objects. In some cases, attempting to interact with existing operations may trigger a crash. This result can occur if the TransferBehavior property is set to Parallel. This issue occurs only in certain scenarios during development and is not applicable to end users of your app.
Four scenarios using Visual Studio can cause this issue.
- You create a new project with the same app name as an existing project, but a different language (from C++ to C#, for example).
- You change the target architecture (from x86 to x64, for example) in an existing project.
- You change the culture (from neutral to en-US, for example) in an existing project.
- You add or remove a capability in the package manifest (adding Enterprise Authentication, for example) in an existing project.
Regular app servicing, including manifest updates which add or remove capabilities, do not trigger this issue on end user deployments of your app.
To work around this issue, completely uninstall all versions of the app and re-deploy with the new language, architecture, culture, or capability. This can be done via the Start screen or using PowerShell and the Remove-AppxPackage cmdlet.
Summary and next steps
In this topic we reviewed how to upload files using the Background Transfer APIs in C#.
You can also download files in your Windows Store app. For an explanation of core concepts and examples of C# implementation, see How to upload a file.
Related topics
Other
Create your first Windows Runtime app using C# or Visual Basic
Create your first Windows Runtime app using C++
How to configure network capabilities
How to handle exceptions in network apps
Transferring data in the background
Reference