Skip to content

Instantly share code, notes, and snippets.

@JerryNixon
Last active December 19, 2016 22:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JerryNixon/1d2265d9293cb268d90a479c968f37ea to your computer and use it in GitHub Desktop.
Save JerryNixon/1d2265d9293cb268d90a479c968f37ea to your computer and use it in GitHub Desktop.
using System.Threading.Tasks;
using Windows.Web.Http;
using System;
using System.Collections.Generic;
using System.Threading;
using Windows.Networking.BackgroundTransfer;
using System.Diagnostics;
using Windows.Storage;
using Windows.Security.Credentials;
using Windows.UI.Notifications;
using Windows.Web.Http.Filters;
namespace Template10.Services.Http
{
public interface ITransferService
{
Task<HttpResponseMessage> DownloadAsync(Uri source, StorageFile file);
Task<IReadOnlyList<DownloadOperation>> GetDownloadQueueAsync();
Task<IReadOnlyList<UploadOperation>> GetUploadQueueAsync();
Task<DownloadOperation> QueueDownloadAsync(Uri source, StorageFile file);
Task<UploadOperation> QueueUploadAsync(Uri target, StorageFile file);
Task<HttpResponseMessage> UploadAsync(Uri target, StorageFile file);
}
public class TransferService : ITransferService
{
TransferHelper _helper;
public TransferService()
{
_helper = new TransferHelper();
}
public async Task<IReadOnlyList<DownloadOperation>> GetDownloadQueueAsync() => await _helper.GetDownloadQueueAsync();
public async Task<IReadOnlyList<UploadOperation>> GetUploadQueueAsync() => await _helper.GetUploadQueueAsync();
public async Task<HttpResponseMessage> UploadAsync(Uri target, StorageFile file) => await _helper.UploadAsync(target, file);
public async Task<HttpResponseMessage> DownloadAsync(Uri source, StorageFile file) => await _helper.DownloadAsync(source, file);
public async Task<UploadOperation> QueueUploadAsync(Uri target, StorageFile file) => await _helper.QueueUploadAsync(target, file);
public async Task<DownloadOperation> QueueDownloadAsync(Uri source, StorageFile file) => await _helper.QueueDownloadAsync(source, file);
}
public class HttpHelper
{
static HttpHelper()
{
_filter = new Lazy<HttpBaseProtocolFilter>(() =>
{
var filter = new HttpBaseProtocolFilter()
{
MaxConnectionsPerServer = 15
};
filter.CacheControl.WriteBehavior = HttpCacheWriteBehavior.Default;
filter.CacheControl.ReadBehavior = HttpCacheReadBehavior.Default;
return filter;
});
_client = new Lazy<HttpClient>(() =>
{
return new HttpClient(_filter.Value);
});
}
static Lazy<HttpClient> _client;
public HttpClient Client => _client.Value;
static Lazy<HttpBaseProtocolFilter> _filter;
public HttpBaseProtocolFilter Filter => _filter.Value;
public IEnumerable<KeyValuePair<string, string>> GetHeaders(HttpResponseMessage response)
{
foreach (var header in response.Headers) yield return header;
foreach (var header in response.Content.Headers) yield return header;
}
}
public class TransferHelper
{
// https://msdn.microsoft.com/en-us/windows/uwp/networking/background-transfers
// https://msdn.microsoft.com/en-us/library/windows/apps/hh943065.aspx?f=255&MSPPError=-2147217396
static TransferHelper()
{
_httpHelper = new HttpHelper();
}
public enum UploadMethods { POST, PUT }
static HttpHelper _httpHelper;
public HttpClient Client = _httpHelper.Client;
public HttpBaseProtocolFilter Filter => _httpHelper.Filter;
public BackgroundTransferCompletionGroup BackgroundTransferCompletionGroup { get; }
public BackgroundTransferGroup BackgroundTransferGroup { get; }
public TimeSpan DefaultTimeout { get; set; } = TimeSpan.FromSeconds(30);
internal TransferHelper()
{
BackgroundTransferGroup = BackgroundTransferGroup.CreateGroup(nameof(TransferHelper));
BackgroundTransferCompletionGroup = new BackgroundTransferCompletionGroup { };
}
public async Task<IReadOnlyList<DownloadOperation>> GetDownloadQueueAsync()
=> await BackgroundDownloader.GetCurrentDownloadsForTransferGroupAsync(BackgroundTransferGroup);
public async Task<IReadOnlyList<UploadOperation>> GetUploadQueueAsync()
=> await BackgroundUploader.GetCurrentUploadsForTransferGroupAsync(BackgroundTransferGroup);
public async Task<HttpResponseMessage> UploadAsync(Uri target, StorageFile file,
HttpMethod method = null, CancellationTokenSource token = null, IProgress<HttpProgress> callback = null)
{
token = token ?? new CancellationTokenSource(DefaultTimeout);
callback = callback ?? new Progress<HttpProgress>(e =>
{ Debug.WriteLine($"{nameof(UploadAsync)}: {e.BytesSent} bytes of {e.TotalBytesToSend} bytes"); });
method = method ?? HttpMethod.Post;
var multipart = new HttpMultipartFormDataContent();
using (var stream = await file.OpenSequentialReadAsync())
{
var content = new HttpStreamContent(stream);
multipart.Add(content, nameof(StorageFile), file.Name);
var request = new HttpRequestMessage(method, target)
{
Content = multipart
};
using (request)
{
return await Client.SendRequestAsync(request).AsTask(token.Token, callback);
}
}
}
public async Task<HttpResponseMessage> DownloadAsync(Uri source, StorageFile file,
CancellationTokenSource token = null, IProgress<HttpProgress> callback = null)
{
token = token ?? new CancellationTokenSource(DefaultTimeout);
callback = callback ?? new Progress<HttpProgress>(e =>
{ Debug.WriteLine($"{nameof(DownloadAsync)}: {e.BytesReceived} bytes of {e.TotalBytesToReceive} bytes"); });
using (var response = await Client.GetAsync(source).AsTask(token.Token, callback))
{
response.EnsureSuccessStatusCode();
if (!response.IsSuccessStatusCode)
{
return response;
}
var buffer = await response.Content.ReadAsBufferAsync();
await FileIO.WriteBufferAsync(file, buffer);
return response;
}
}
public async Task<UploadOperation> QueueUploadAsync(Uri target, StorageFile file, UploadMethods method = UploadMethods.PUT,
PasswordCredential serverCredential = null, PasswordCredential proxyCredential = null,
BackgroundTransferCostPolicy policy = BackgroundTransferCostPolicy.Default,
BackgroundTransferPriority priority = BackgroundTransferPriority.Default,
ToastNotification successToastNotification = null, ToastNotification failureToastNotification = null,
TileNotification successTileNotification = null, TileNotification failureTileNotification = null,
CancellationTokenSource token = null, IProgress<UploadOperation> callback = null)
{
token = token ?? new CancellationTokenSource(DefaultTimeout);
callback = callback ?? new Progress<UploadOperation>(e =>
{ Debug.WriteLine($"{nameof(QueueUploadAsync)}: {e.Progress.BytesReceived} bytes of {e.Progress.TotalBytesToReceive} bytes"); });
var uploader = new BackgroundUploader(BackgroundTransferCompletionGroup)
{
ServerCredential = serverCredential,
ProxyCredential = proxyCredential,
Method = method.ToString(),
TransferGroup = BackgroundTransferGroup,
CostPolicy = policy,
SuccessToastNotification = successToastNotification,
FailureToastNotification = failureToastNotification,
SuccessTileNotification = successTileNotification,
FailureTileNotification = failureTileNotification,
};
uploader.SetRequestHeader("Filename", file.Name);
return await uploader.CreateUpload(target, file).StartAsync().AsTask(token.Token, callback);
}
public async Task<DownloadOperation> QueueDownloadAsync(Uri source, StorageFile file,
PasswordCredential serverCredential = null, PasswordCredential proxyCredential = null,
BackgroundTransferCostPolicy policy = BackgroundTransferCostPolicy.Default,
BackgroundTransferPriority priority = BackgroundTransferPriority.Default,
ToastNotification successToastNotification = null, ToastNotification failureToastNotification = null,
TileNotification successTileNotification = null, TileNotification failureTileNotification = null,
CancellationTokenSource token = null, IProgress<DownloadOperation> callback = null)
{
token = token ?? new CancellationTokenSource(DefaultTimeout);
callback = callback ?? new Progress<DownloadOperation>(e =>
{ Debug.WriteLine($"{nameof(QueueDownloadAsync)}: {e.Progress.BytesReceived} bytes of {e.Progress.TotalBytesToReceive} bytes"); });
var downloader = new BackgroundDownloader(BackgroundTransferCompletionGroup)
{
ServerCredential = serverCredential,
ProxyCredential = proxyCredential,
TransferGroup = BackgroundTransferGroup,
CostPolicy = policy,
SuccessToastNotification = successToastNotification,
FailureToastNotification = failureToastNotification,
SuccessTileNotification = successTileNotification,
FailureTileNotification = failureTileNotification,
};
return await downloader.CreateDownload(source, file).StartAsync().AsTask(token.Token, callback);
}
public ToastNotification SimpleToastNotification(string text = "Background operation completed")
{
var xml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01);
var nodes = xml.GetElementsByTagName("text");
nodes.Item(0).InnerText = text;
return new ToastNotification(xml);
}
public TileNotification SimpleTileNotification(string text = "Background operation completed")
{
var xml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150Text04);
var nodes = xml.GetElementsByTagName("text");
nodes.Item(0).InnerText = text;
return new TileNotification(xml);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment