Last active
December 19, 2016 22:04
-
-
Save JerryNixon/1d2265d9293cb268d90a479c968f37ea to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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