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; } } }
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); } }
private static async Task <HttpWebResponse> GetHttpResponseAsync(HttpWebRequest request) { await semaphoreSlimGetHttpResponse.WaitAsync(); try { cnt++; if ((DateTime.Now - time).TotalSeconds > 30) { MyLogger.Log($"{cnt} requests from {DateTime.Now} to {time}"); time = DateTime.Now; cnt = 0; //await MyLogger.Alert($"cnt={a}"); } HttpWebResponse ans; int minisecs = 500; indexRetry :; try { ans = (await request.GetResponseAsync()) as HttpWebResponse; } catch (WebException error) { ans = error.Response as HttpWebResponse; } finally { request.Abort(); } if (ans == null) { MyLogger.Log("Got null response"); return(null); } switch (ans.StatusCode) { case HttpStatusCode.InternalServerError: case HttpStatusCode.BadGateway: case HttpStatusCode.ServiceUnavailable: case HttpStatusCode.GatewayTimeout: case HttpStatusCode.Forbidden: { MyLogger.Log(await LogHttpWebResponse(ans, true)); if (minisecs > Constants.MaxTimeToWait) { MyLogger.Log("Attempted to reconnect but still failed."); return(ans); } else { MyLogger.Log($"Response: {ans.StatusCode} ({(int)ans.StatusCode}), waiting for {minisecs} ms and try again..."); await Task.Delay(minisecs); minisecs *= 2; goto indexRetry; } } case HttpStatusCode.Unauthorized: { MyLogger.Log("Http response: Unauthorized (401). May due to expired access token, refreshing..."); MyLogger.Log(await LogHttpWebResponse(ans, true)); MyLogger.Assert(Array.IndexOf(request.Headers.AllKeys, "Authorization") != -1); request.Headers["Authorization"] = "Bearer " + (await Drive.RefreshAccessTokenAsync()); await Task.Delay(500); goto indexRetry; } default: return(ans); } } finally { lock (semaphoreSlimGetHttpResponse) semaphoreSlimGetHttpResponse.Release(); } }
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 static void Main(string[] args) { #region Validate args if (args.Length > 0) { if (args.Length > 1) { PrintUsageAndExit(1); } else if ( args[0] != "/RefreshList" && (!args[0].StartsWith("/RootFolderId=") || args[0].Length<15) && (!args[0].StartsWith("/PresentationId=") || args[0].Length < 17) && args[0] != "/Students" && (!args[0].StartsWith("/StartFromSheet=") || args[0].Length < 17) ) { PrintUsageAndExit(2); } } #endregion LogOutputWithNewLine("Started..."); drive = new Drive(); drive.PresentationProcessed += Drive_PresentationProcessed; drive.PresentationError += Drive_PresentationError; drive.FolderProcessingStarted += Drive_FolderProcessingStarted; drive.PresentationSkipped += Drive_PresentationSkipped; #region Parse args string presentationId = null; string specificFolderId = null; string startFromSheet = null; if (args.Length > 0) { if (args[0] == "/?") { PrintUsageAndExit(0); } else if (args[0].StartsWith("/RootFolderId=")) { specificFolderId = args[0].Split('=')[1]; processingType = ProcessingType.TEACHER_FOLDER; } else if (args[0].StartsWith("/PresentationId=")) { presentationId = args[0].Split('=')[1]; processingType = ProcessingType.TEACHER_PRESENTATION; } else if (args[0] == "/Students") { processingType = ProcessingType.STUDENTS; } else if (args[0].StartsWith("/StartFromSheet=")) { startFromSheet = args[0].Split('=')[1]; processingType = ProcessingType.STUDENTS; } } else { processingType = ProcessingType.TEACHER_FOLDER; } #endregion switch (processingType) { case ProcessingType.TEACHER_PRESENTATION: #region Process specfic presentation LogOutputWithNewLine(string.Format("Processing specific teacher presentation: {0}", presentationId)); var cachePresentation = drive.TeacherCache.GetPresentation(presentationId, drive.TeacherCache.Folders); if (cachePresentation != null) { drive.ProcessTeacherPresentation(cachePresentation); } else { LogOutputWithNewLine(string.Format("Presentation {0} not found in cache", presentationId)); } break; #endregion case ProcessingType.TEACHER_FOLDER: #region Process folder presentations var rootFolderId = ConfigurationManager.AppSettings["rootFolderId"]; CacheFolder rootFolder; if (specificFolderId != null) { rootFolder = drive.TeacherCache.GetFolder(specificFolderId, drive.TeacherCache.Folders); if (rootFolder == null) { //Specified folder id not found in cache PrintUsageAndExit(3); } drive.ProcessTeacherPresentations(rootFolder); } else { LogOutputWithNewLine(string.Format("Start processing {0} teacher presentations...", drive.TeacherCache.TotalPresentations)); foreach (var folderKey in drive.TeacherCache.Folders.Keys) { drive.ProcessTeacherPresentations(drive.TeacherCache.Folders[folderKey]); } } break; #endregion case ProcessingType.STUDENTS: if (startFromSheet != null) { if (drive.StudentsCache.GetSubFolderByName(startFromSheet) != null) { LogOutputWithNewLine(string.Format("Processing student presentations, starting from sheet {0}...", startFromSheet)); drive.ProcessStudentsPresentations(startFromSheet); } else { LogOutputWithNewLine(string.Format("Sheet {0} does not exist", startFromSheet)); } } else { LogOutputWithNewLine("Processing student presentations..."); drive.ProcessStudentsPresentations(); } break; } LogOutputWithNewLine("Finished..."); }