public async Task PauseAsync() { switch (Status) { case DownloadStatus.Downloading: { pauseRequest = true; MessageAppended?.Invoke("Pausing..."); while (Status == DownloadStatus.Downloading) { await Task.Delay(100); } MessageAppended?.Invoke("Paused"); pauseRequest = false; return; } case DownloadStatus.Completed: case DownloadStatus.ErrorNeedRestart: case DownloadStatus.ErrorNeedResume: case DownloadStatus.NotStarted: case DownloadStatus.Paused: default: { throw new Exception($"Status: {Status}"); } } }
public async Task Start() { int timeToWait = 500; while(true) { await StartPrivate(); switch (Status) { case FileCreatorStatus.ErrorNeedRestart: { if (timeToWait >Constants.MaxTimeToWait) return; MessageAppended?.Invoke($"Waiting for {timeToWait} and try again..."); timeToWait *= 2; }break; case FileCreatorStatus.Completed: { return; } default: { throw new Exception($"Status: {Status}"); } } } }
private async Task StartPrivate() { Status = FileCreatorStatus.Creating; MessageAppended?.Invoke("Creating Folder..."); string json = $"{{\"name\":\"{name}\",\"parents\":[\"{cloudId}\"]"; if(isFolder) { json += ",\"mimeType\": \"application/vnd.google-apps.folder\""; } json += "}"; MessageAppended?.Invoke(json); HttpWebRequest request = WebRequest.CreateHttp("https://www.googleapis.com/drive/v3/files"); var bytes = Encoding.UTF8.GetBytes(json); request.Headers["Content-Type"] = "application /json; charset=UTF-8"; request.Headers["Content-Length"] = bytes.Length.ToString(); request.Headers["Authorization"] = "Bearer " + (await Drive.GetAccessTokenAsync()); request.Method = "POST"; using (System.IO.Stream requestStream = await request.GetRequestStreamAsync()) { await requestStream.WriteAsync(bytes, 0, bytes.Length); } using (var response = await GetHttpResponseAsync(request)) { if (response == null) { MessageAppended?.Invoke("Null response"); Status = FileCreatorStatus.ErrorNeedRestart; return; } MessageAppended?.Invoke($"Http response: {response.StatusCode} ({(int)response.StatusCode})"); if (response.StatusCode == HttpStatusCode.OK) { using (var reader = new System.IO.StreamReader(response.GetResponseStream())) { var jsonObj = JsonConvert.DeserializeObject<Dictionary<string, string>>(await reader.ReadToEndAsync()); if (!jsonObj.ContainsKey("id")) { MessageAppended?.Invoke("response.Headers doesn't contain a key for \"id\"!"); MessageAppended?.Invoke(await LogHttpWebResponse(response, true)); Status = FileCreatorStatus.ErrorNeedRestart; return; } Result= jsonObj["id"]; MessageAppended?.Invoke($"Folder {name} ({Result}) created!"); Status = FileCreatorStatus.Completed; return; } } else { MessageAppended?.Invoke("Http response isn't OK!"); MessageAppended?.Invoke(await LogHttpWebResponse(response, true)); Status = FileCreatorStatus.ErrorNeedRestart; return; } } }
private void AddMessage(ScriptMessageType type, string message) { var msg_info = new ScriptMessageData(DateTime.UtcNow, type, message); lock (message_list_sync_) { message_list_.Add(msg_info); } MessageAppended?.Invoke(this, msg_info); }
private async Task StartDownloadAsync() { Status = DownloadStatus.Downloading; MyLogger.Assert(fileStream != null && resumableUri != null); try { if (!await CreateResumableDownloadAsync()) { Status = DownloadStatus.ErrorNeedRestart; MessageAppended?.Invoke("Error create resumable download async"); return; } var fileSize = bytesReceivedSoFar + serverStreamLength; MyLogger.Log($"File size = {fileSize}"); fileStream.Position = bytesReceivedSoFar; int chunkSize = MinChunkSize; for (; bytesReceivedSoFar != fileSize;) { DateTime startTime = DateTime.Now; var bufferSize = (int)Math.Min(chunkSize, fileSize - bytesReceivedSoFar); if (pauseRequest) { Status = DownloadStatus.Paused; return; } var bytesRead = await DoResumableDownloadAsync(bufferSize); if (Status == DownloadStatus.ErrorNeedResume) { MessageAppended?.Invoke($"Failed! Chunk range: {bytesReceivedSoFar}-{bytesReceivedSoFar + bufferSize - 1}"); return; } MyLogger.Assert(Status == DownloadStatus.Downloading && bytesRead != -1); bytesReceivedSoFar += bytesRead; if ((DateTime.Now - startTime).TotalSeconds < 0.2) { chunkSize = (int)Math.Min((long)chunkSize + chunkSize / 2, int.MaxValue); } else { chunkSize = Math.Max(MinChunkSize, chunkSize / 2); } OnProgressChanged(bytesReceivedSoFar, fileSize); } OnProgressChanged(fileSize, fileSize); Status = DownloadStatus.Completed; } catch (Exception error) { Status = DownloadStatus.ErrorNeedResume; MessageAppended?.Invoke(error.ToString()); } }
public async Task <string> GetNextPageWithFieldsAsync(string fields, int pageSize = 100) { Status = Networker.NetworkStatus.Networking; if (searchListGetter == null) { searchListGetter = new RestRequests.SearchListGetter(searchPattern); searchListGetter.MessageAppended += (msg) => { MessageAppended?.Invoke($"[Rest]{msg}"); }; pageNumber = 0; } MessageAppended?.Invoke($"Getting page #{++pageNumber}"); if (searchListGetter.Status == RestRequests.SearchListGetter.SearchStatus.Completed) { Status = Networker.NetworkStatus.Completed; return(null); } searchListGetter.PageSize = pageSize; int timeToWait = 500; index_tryAgain :; await searchListGetter.GetNextPageAsync(fields); if (searchListGetter.Status == RestRequests.SearchListGetter.SearchStatus.Paused) { Status = Networker.NetworkStatus.Paused; return(searchListGetter.NextPageString); } else if (searchListGetter.Status == RestRequests.SearchListGetter.SearchStatus.Completed) { Status = Networker.NetworkStatus.Completed; return(searchListGetter.NextPageString); } else { MessageAppended?.Invoke($"searchListGetter.Status: {searchListGetter.Status}"); if (searchListGetter.Status == RestRequests.SearchListGetter.SearchStatus.ErrorNeedResume) { if (timeToWait > Constants.MaxTimeToWait) { Status = Networker.NetworkStatus.ErrorNeedRestart; return(null); } MessageAppended?.Invoke($"Waiting for {timeToWait} milisecs and try again..."); await Task.Delay(timeToWait); timeToWait *= 2; goto index_tryAgain; } Status = Networker.NetworkStatus.ErrorNeedRestart; return(null); } }
public async Task PauseAsync() { switch (Status) { case UploadStatus.Uploading: case UploadStatus.Creating: case UploadStatus.Created: { MessageAppended?.Invoke("Pausing..."); pauseRequest = true; await semaphoreSlim.WaitAsync(10000); //MyLogger.Assert(Status != UploadStatus.Uploading); //while (Status == UploadStatus.Uploading) await Task.Delay(100); pauseRequest = false; if (Status == UploadStatus.Uploading) { var msg = $"Status: {Status}, failed to pause"; MyLogger.Log(msg); MessageAppended?.Invoke(msg); } //MessageAppended?.Invoke($"Status after paused: {Status}"); //if () await MyLogger.Alert($"Status after paused: {Status}"); return; } case UploadStatus.Completed: case UploadStatus.ErrorNeedRestart: case UploadStatus.ErrorNeedResume: case UploadStatus.NotStarted: case UploadStatus.Paused: { MyLogger.Log($"Status: {Status}, no action take to pause"); return; } default: { throw new Exception($"Status: {Status}"); } } }
private async Task <long> DoResumableDownloadAsync(int bufferSize) { try { var buffer = new byte[bufferSize]; var bytesRead = await serverStream.ReadAsync(buffer, 0, bufferSize); await fileStream.WriteAsync(buffer, 0, bytesRead); await fileStream.FlushAsync(); return(bytesRead); } catch (Exception error) { MessageAppended?.Invoke(error.ToString()); Status = DownloadStatus.ErrorNeedResume; return(-1); } }
public async Task StartAsync() { pauseRequest = false; while (true) { if (pauseRequest) { MessageAppended?.Invoke("Paused."); Status = Networker.NetworkStatus.Paused; return; } var ans = await GetNextPageAsync(); if (ans == null) { break; } NewFileListGot?.Invoke(ans); } MessageAppended?.Invoke("Done."); }
public async Task GetNextPageAsync(string fields = "nextPageToken,incompleteSearch,files(id,name,mimeType)") { string url = $"https://www.googleapis.com/drive/v3/files?corpora=user&fields={fields}"; url += $"&pageSize={pageSize}"; if (pageToken != null) { url += $"&pageToken={pageToken}"; } url += $"&q={System.Net.WebUtility.UrlEncode(searchPattern)}"; HttpWebRequest request = WebRequest.CreateHttp(url); //MessageAppended?.Invoke($"url: {url}"); request.Headers["Authorization"] = "Bearer " + (await Drive.GetAccessTokenAsync()); request.Method = "GET"; using (var response = await GetHttpResponseAsync(request)) { if (response == null) { MessageAppended?.Invoke("Null response"); Status = SearchStatus.ErrorNeedResume; return; } MessageAppended?.Invoke($"Http response: {response.StatusCode} ({(int)response.StatusCode})"); if (response.StatusCode == HttpStatusCode.OK) { string resultText; using (var responseStream = response.GetResponseStream()) { using (var reader = new System.IO.StreamReader(responseStream)) { resultText = await reader.ReadToEndAsync(); } } NextPageString = resultText; var result = JsonConvert.DeserializeObject <temporaryClassForResponseBody>(resultText); if (result.incompleteSearch) { MessageAppended?.Invoke("Warning! This is an Incomplete Search"); MyLogger.Log("Warning! This is an Incomplete Search"); } FileListGot.Clear(); if (result.files != null) { foreach (var file in result.files) { FileListGot.Add(new Tuple <string, string, string>(file.id, file.name, file.mimeType)); } } NewFileListGot?.Invoke(FileListGot); if (result.nextPageToken == null) { Status = SearchStatus.Completed; } else { pageToken = result.nextPageToken; Status = SearchStatus.Paused; } return; } else { MessageAppended?.Invoke("Http response isn't OK!"); MessageAppended?.Invoke(await LogHttpWebResponse(response, true)); Status = SearchStatus.ErrorNeedResume; return; } } }
protected void OnMessageAppended(string msg) { messages.Add(msg); MessageAppended?.Invoke(msg); }
public async Task <List <CloudFile> > GetNextPageAsync(int pageSize = 100) { Status = Networker.NetworkStatus.Networking; if (searchListGetter == null) { searchListGetter = new RestRequests.SearchListGetter(searchPattern); searchListGetter.MessageAppended += (msg) => { MessageAppended?.Invoke($"[Rest]{msg}"); }; MessageAppended?.Invoke("Getting first page..."); } else { MessageAppended?.Invoke("Getting next page..."); } if (searchListGetter.Status == RestRequests.SearchListGetter.SearchStatus.Completed) { Status = Networker.NetworkStatus.Completed; return(null); } searchListGetter.PageSize = pageSize; int timeToWait = 500; index_tryAgain :; await searchListGetter.GetNextPageAsync(); if (searchListGetter.Status == RestRequests.SearchListGetter.SearchStatus.Paused) { var ans = searchListGetter.FileListGot.Select((file) => { return(new CloudFile(file.Item1, file.Item2, file.Item3 == Constants.FolderMimeType, parent)); }).ToList(); Status = Networker.NetworkStatus.Paused; return(ans); } else if (searchListGetter.Status == RestRequests.SearchListGetter.SearchStatus.Completed) { var ans = searchListGetter.FileListGot.Select((file) => { return(new CloudFile(file.Item1, file.Item2, file.Item3 == Constants.FolderMimeType, parent)); }).ToList(); Status = Networker.NetworkStatus.Completed; return(ans); } else { MessageAppended?.Invoke($"searchListGetter.Status: {searchListGetter.Status}"); if (searchListGetter.Status == RestRequests.SearchListGetter.SearchStatus.ErrorNeedResume) { if (timeToWait > Constants.MaxTimeToWait) { Status = Networker.NetworkStatus.ErrorNeedRestart; return(null); } MessageAppended?.Invoke($"Waiting for {timeToWait} milisecs and try again..."); await Task.Delay(timeToWait); timeToWait *= 2; goto index_tryAgain; } Status = Networker.NetworkStatus.ErrorNeedRestart; return(null); } }
private async Task CreateResumableUploadAsync() { Status = UploadStatus.Creating; string json = $"{{\"name\":\"{fileName}\""; if (parents.Count > 0) { json += ",\"parents\":["; foreach (string parent in parents) { json += $"\"{parent}\","; } json = json.Remove(json.Length - 1) + "]"; } json += "}"; MessageAppended?.Invoke(json); long totalBytes = fileStream.Length; HttpWebRequest request = WebRequest.CreateHttp("https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable"); var bytes = Encoding.UTF8.GetBytes(json); request.Headers["Content-Type"] = "application /json; charset=UTF-8"; request.Headers["Content-Length"] = bytes.Length.ToString(); // Convert.FromBase64String(json).Length.ToString(); //request.Headers["X-Upload-Content-Type"]= Constants.GetMimeType(System.IO.Path.GetExtension(filePath)); request.Headers["X-Upload-Content-Length"] = totalBytes.ToString(); request.Headers["Authorization"] = "Bearer " + (await Drive.GetAccessTokenAsync()); request.Method = "POST"; using (System.IO.Stream requestStream = await request.GetRequestStreamAsync()) { await requestStream.WriteAsync(bytes, 0, bytes.Length); //using (System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(requestStream)) //{ // await streamWriter.WriteAsync(json); //} } using (var response = await GetHttpResponseAsync(request)) { if (response == null) { MessageAppended?.Invoke("Null response"); Status = UploadStatus.ErrorNeedRestart; return; } MessageAppended?.Invoke($"Http response: {response.StatusCode} ({(int)response.StatusCode})"); if (response.StatusCode == HttpStatusCode.OK) { if (Array.IndexOf(response.Headers.AllKeys, "location") == -1) { MessageAppended?.Invoke("response.Headers doesn't contain a key for \"location\"!"); Status = UploadStatus.ErrorNeedRestart; return; } var resumableUri = JsonConvert.SerializeObject(response.Headers["location"]); MessageAppended?.Invoke($"Resumable Uri: {resumableUri}"); this.resumableUri = resumableUri; Status = UploadStatus.Created; return; } else { MessageAppended?.Invoke("Http response isn't OK!"); MessageAppended?.Invoke(await LogHttpWebResponse(response, true)); Status = UploadStatus.ErrorNeedRestart; return; } } }
private void Runner_MessageAppended(object sender, ScriptMessageData msg) { MessageAppended?.Invoke(this, msg); }
//private async Task<UploadStatus> VerifyCheckSum() //{ // MessageAppended?.Invoke("Calculating checksum..."); // string cloudCheckSum = await Libraries.GetSha256ForCloudFileById(CloudFileId); // MessageAppended?.Invoke($"Cloud: {cloudCheckSum}"); // fileStream.Position = 0; // string localCheckSum = await Libraries.GetSha256ForWindowsStorageFile(fileStream); // MessageAppended?.Invoke($"Local: {localCheckSum}"); // if (cloudCheckSum != null && cloudCheckSum == localCheckSum) // { // MessageAppended?.Invoke("Checksum matched!"); // return UploadStatus.Completed; // } // else // { // MessageAppended?.Invoke("Failed: Checksum not matched"); // return UploadStatus.ErrorNeedRestart; // } //} private async Task StartUploadAsync(long position) { if (pauseRequest) { Status = UploadStatus.Paused; lock (semaphoreSlim) semaphoreSlim.Release(); return; } Status = UploadStatus.Uploading; long chunkSize = MinChunkSize; long bytesLeftStatistics = fileStream.Length - position; CloudFile.Networker.OnTotalAmountRemainChanged(bytesLeftStatistics); try { for (; position != fileStream.Length;) { var bufferSize = Math.Min(chunkSize, fileStream.Length - position); byte[] buffer = new byte[bufferSize]; int actualLength = 0; while (actualLength < Math.Min(bufferSize, MinChunkSize)) { fileStream.Position = position + actualLength; actualLength += await fileStream.ReadAsync(buffer, actualLength, (int)bufferSize - actualLength); } Array.Resize <byte>(ref buffer, actualLength); DateTime startTime = DateTime.Now; await DoResumableUploadAsync(position, buffer); OnProgressChanged(position = byteReceivedSoFar, fileStream.Length); if (Status == UploadStatus.Completed) { OnChunkSent(buffer.Length); bytesLeftStatistics -= buffer.Length; CloudFile.Networker.OnTotalAmountRemainChanged(-buffer.Length); return; } else if (Status != UploadStatus.Uploading) { MessageAppended?.Invoke($"Failed! Chunk range: {position}-{position + buffer.Length - 1}"); return; } else { OnChunkSent(buffer.Length); bytesLeftStatistics -= buffer.Length; CloudFile.Networker.OnTotalAmountRemainChanged(-buffer.Length); } if ((DateTime.Now - startTime).TotalSeconds < 0.2) { chunkSize += chunkSize / 2; } else { chunkSize = Math.Max(MinChunkSize, chunkSize / 2); } //MyLogger.Log($"Sent: {i + chunkSize}/{fileStream.Length} bytes"); if (pauseRequest) { Status = UploadStatus.Paused; lock (semaphoreSlim) semaphoreSlim.Release(); return; } } } finally { CloudFile.Networker.OnTotalAmountRemainChanged(-bytesLeftStatistics); } }
private async Task DoResumableUploadAsync(long startByte, byte[] dataBytes) { var request = WebRequest.CreateHttp(resumableUri); request.Headers["Content-Length"] = dataBytes.Length.ToString(); request.Headers["Content-Range"] = $"bytes {startByte}-{startByte + dataBytes.Length - 1}/{fileStream.Length}"; request.Method = "PUT"; using (System.IO.Stream requestStream = await request.GetRequestStreamAsync()) { await requestStream.WriteAsync(dataBytes, 0, dataBytes.Length); } using (var response = await GetHttpResponseAsync(request)) { if (response == null) { MyLogger.Log("b"); Status = UploadStatus.ErrorNeedResume; return; } if ((int)response.StatusCode == 308) { if (Array.IndexOf(response.Headers.AllKeys, "range") == -1) { MessageAppended?.Invoke("No bytes have been received by the server yet, starting from the first byte..."); byteReceivedSoFar = 0; } else { //bytes=0-42 string s = response.Headers["range"]; //MyLogger.Log($"Range received by server: {s}"); string pattern = "bytes=0-"; MyLogger.Assert(s.StartsWith(pattern)); byteReceivedSoFar = long.Parse(s.Substring(pattern.Length)) + 1; } return; } else if (response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Created) { using (var reader = new System.IO.StreamReader(response.GetResponseStream())) { var data = await reader.ReadToEndAsync(); //MyLogger.Log($"{data}"); var jsonObject = JsonConvert.DeserializeObject <Newtonsoft.Json.Linq.JObject>(data); MyLogger.Assert(fileName == (string)jsonObject["name"]); CloudFileId = (string)jsonObject["id"]; } byteReceivedSoFar = fileStream.Length; Status = UploadStatus.Completed; return; } else { MessageAppended?.Invoke("Http response isn't 308!"); MessageAppended?.Invoke(await LogHttpWebResponse(response, true)); Status = UploadStatus.ErrorNeedResume; return; } } }
public async Task UploadAsync() { try { switch (Status) { case UploadStatus.ErrorNeedResume: case UploadStatus.Paused: { MyLogger.Assert(resumableUri != null); //indexRetry:; MessageAppended?.Invoke($"Resuming... Uri: {resumableUri}"); var request = WebRequest.CreateHttp(resumableUri); request.Headers["Content-Length"] = "0"; request.Headers["Content-Range"] = $"bytes */{fileStream.Length}"; request.Method = "PUT"; using (var response = await GetHttpResponseAsync(request)) { if (response == null) { MyLogger.Log("c"); MessageAppended?.Invoke("Null response"); Status = UploadStatus.ErrorNeedResume; return; } MessageAppended?.Invoke($"Http response: {response.StatusCode} ({response.StatusCode})"); if (response.StatusCode == HttpStatusCode.OK || response.StatusCode == HttpStatusCode.Created) { MessageAppended?.Invoke("The upload was already completed"); MessageAppended?.Invoke(await LogHttpWebResponse(response, false)); using (var reader = new System.IO.StreamReader(response.GetResponseStream())) { var data = await reader.ReadToEndAsync(); var jsonObject = JsonConvert.DeserializeObject <Newtonsoft.Json.Linq.JObject>(data); MyLogger.Assert(fileName == (string)jsonObject["name"]); CloudFileId = (string)jsonObject["id"]; } response.Dispose(); Status = UploadStatus.Completed; return; } else if ((int)response.StatusCode == 308) { long position; if (Array.IndexOf(response.Headers.AllKeys, "range") == -1) { MessageAppended?.Invoke("No bytes have been received by the server yet, starting from the first byte..."); position = 0; } else { //bytes=0-42 string s = response.Headers["range"]; MessageAppended?.Invoke($"Range received by server: {s}"); string pattern = "bytes=0-"; MyLogger.Assert(s.StartsWith(pattern)); position = long.Parse(s.Substring(pattern.Length)); } response.Dispose(); await StartUploadAsync(position); return; } else if (response.StatusCode == HttpStatusCode.NotFound) { MessageAppended?.Invoke("The upload session has expired and the upload needs to be restarted from the beginning."); MessageAppended?.Invoke(await LogHttpWebResponse(response, true)); response.Dispose(); Status = UploadStatus.ErrorNeedRestart; return; } else { MessageAppended?.Invoke("Http response isn't OK, Created or 308!"); MessageAppended?.Invoke(await LogHttpWebResponse(response, true)); response.Dispose(); Status = UploadStatus.ErrorNeedResume; return; } } } case UploadStatus.NotStarted: { if (fileStream.Length < MinChunkSize) { MessageAppended?.Invoke($"File too small ({fileStream.Length}), using multipart upload instead"); await DoMultipartUploadAsync(); } else { await CreateResumableUploadAsync(); if (Status != UploadStatus.Created) { return; } MyLogger.Assert(resumableUri.StartsWith("\"") && resumableUri.EndsWith("\"")); resumableUri = resumableUri.Substring(1, resumableUri.Length - 2); await StartUploadAsync(0); } return; } case UploadStatus.Completed: case UploadStatus.Created: case UploadStatus.Creating: case UploadStatus.ErrorNeedRestart: case UploadStatus.Uploading: default: throw new Exception($"Status: {Status}"); } } finally { if (pauseRequest) { MyLogger.Assert(Status != UploadStatus.Uploading); lock (semaphoreSlim) semaphoreSlim.Release(); } } }
private async Task DoMultipartUploadAsync() { Status = UploadStatus.Uploading; OnProgressChanged(0, fileStream.Length); CloudFile.Networker.OnTotalAmountRemainChanged(fileStream.Length); try { var body = MergeMetadataAndFileContent(new Func <byte[]>(() => { string json = $"Content-Type: application/json; charset=UTF-8\n\n{{\"name\":\"{fileName}\""; if (parents.Count > 0) { json += ",\"parents\":["; foreach (string parent in parents) { json += $"\"{parent}\","; } json = json.Remove(json.Length - 1) + "]"; } json += "}"; MessageAppended?.Invoke(json); return(Encoding.UTF8.GetBytes(json)); })(), await new Func <Task <byte[]> >(async() => { byte[] buffer = new byte[fileStream.Length]; for (int i = 0; i < buffer.Length;) { i += await fileStream.ReadAsync(buffer, i, buffer.Length - i); } return(buffer); })()); //MessageAppended?.Invoke($"Request to send:\r\n{Encoding.UTF8.GetString(body.Item2)}"); //long totalBytes = fileStream.Length; HttpWebRequest request = WebRequest.CreateHttp("https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart"); request.Headers["Content-Type"] = "multipart/related; charset=UTF-8; boundary=" + body.Item1; request.Headers["Content-Length"] = body.Item2.Length.ToString(); // Convert.FromBase64String(json).Length.ToString(); //request.Headers["X-Upload-Content-Type"]= Constants.GetMimeType(System.IO.Path.GetExtension(filePath)); //request.Headers["X-Upload-Content-Length"] = totalBytes.ToString(); request.Headers["Authorization"] = "Bearer " + (await Drive.GetAccessTokenAsync()); request.Method = "POST"; using (System.IO.Stream requestStream = await request.GetRequestStreamAsync()) { await requestStream.WriteAsync(body.Item2, 0, body.Item2.Length); } using (var response = await GetHttpResponseAsync(request)) { if (response == null) { MessageAppended?.Invoke("Null response"); Status = UploadStatus.ErrorNeedRestart; return; } MessageAppended?.Invoke($"Http response: {response.StatusCode} ({(int)response.StatusCode})"); if (response.StatusCode == HttpStatusCode.OK) { OnProgressChanged(fileStream.Length, fileStream.Length); OnChunkSent(fileStream.Length); Status = UploadStatus.Completed; return; } else { MessageAppended?.Invoke("Http response isn't OK!"); MessageAppended?.Invoke(await LogHttpWebResponse(response, true)); Status = UploadStatus.ErrorNeedRestart; return; } } } finally { CloudFile.Networker.OnTotalAmountRemainChanged(-fileStream.Length); } }