2017-08-23 20 views
1

私はWindowsに組み込まれているクライアントアプリケーションが私が理解できない理由で失敗しているため、OneDriveデスクトップクライアントアプリケーションを開発しています。私はC#でHttpClient経由でREST APIを使用しています。OneDrive API再開可能なアップロードURLが応答しない

onedriveエンドポイントへのすべてのリクエストはうまく動作します(ダウンロード、小さなファイルのアップロードなど)。大きなファイルのアップロードは、最近まで(約2日前まで)正常に機能しました。アップロードセッションURLを取得してデータをアップロードしますが、2つのチャンクを正常にアップロードした後(202応答)、3番目の要求以降は(HttpClientを介して)GETのステータスを取得するかどうか、またはデータをアップロードするPUTセッションを作成するためのPOSTはまだ動作します。

新しいClientIdを取得し、新しいMicrosoftアカウントにログインし、コードを既知の動作状態に戻し、gitリポジトリを再クローンしました。

PostManではセッションを作成してチャンクをアップロードし、この問題は発生しませんが、アプリケーションがOneDrive APIから取得するアップロードURLを取得して、PUTのデータを試してみることができますPostManでは、サーバーは応答しません(要求が無効でない限り、時々私に知らせる)。このURLへのその後のGETリクエストも応答しません。

はここで認証後OneDrive APIに行くすべての要求のログです:https://pastebin.com/qRrw2Sb5

をし、ここに関連するコードです:

//first, create an upload session 
var httpResponse = await _httpClient.StartAuthenticatedRequest(url, HttpMethod.Post).SendAsync(ct); 
if (httpResponse.StatusCode != HttpStatusCode.OK) 
{ 
    return new HttpResult<IRemoteItemHandle>(httpResponse, null); 
} 


//get the upload URL 
var uploadSessionRequestObject = await HttpClientHelper.ReadResponseAsJObjectAsync(httpResponse); 

var uploadUrl = (string)uploadSessionRequestObject["uploadUrl"]; 
if (uploadUrl == null) 
{ 
    Debug.WriteLine("Successful OneDrive CreateSession request had invalid body!"); 
    //TODO: what to do here? 
} 

//the length of the file total 
var length = data.Length; 

//setup the headers 
var headers = new List<KeyValuePair<string, string>>() 
{ 
    new KeyValuePair<string, string>("Content-Length", ""), 
    new KeyValuePair<string, string>("Content-Range","") 
}; 

JObject responseJObject; 
//the response that will be returned 
HttpResponseMessage response = null; 

//get the chunks 
List<Tuple<long, long>> chunks; 
do 
{ 

    HttpResult<List<Tuple<long, long>>> chunksResult; 
    //get the chunks 
    do 
    { 
     chunksResult = await RetrieveLargeUploadChunksAsync(uploadUrl, _10MB, length, ct); 
     //TODO: should we delay on failure? 
    } while (chunksResult.Value == null);//keep trying to get thre results until we're successful 

    chunks = chunksResult.Value; 

    //upload each fragment 
    var chunkStream = new ChunkedReadStreamWrapper(data); 
    foreach (var fragment in chunks) 
    { 
     //setup the chunked stream with the next fragment 
     chunkStream.ChunkStart = fragment.Item1; 

     //the size is one more than the difference (because the range is inclusive) 
     chunkStream.ChunkSize = fragment.Item2 - fragment.Item1 + 1; 

     //setup the headers for this request 
     headers[0] = new KeyValuePair<string, string>("Content-Length", chunkStream.ChunkSize.ToString()); 
     headers[1] = new KeyValuePair<string, string>("Content-Range", $"bytes {fragment.Item1}-{fragment.Item2}/{length}"); 

     //submit the request until it is successful 
     do 
     { 
      //this should not be authenticated 
      response = await _httpClient.StartRequest(uploadUrl, HttpMethod.Put) 
       .SetContent(chunkStream) 
       .SetContentHeaders(headers) 
       .SendAsync(ct); 

     } while (!response.IsSuccessStatusCode); // keep retrying until success 
    } 

    //parse the response to see if there are more chunks or the final metadata 
    responseJObject = await HttpClientHelper.ReadResponseAsJObjectAsync(response); 

    //try to get chunks from the response to see if we need to retry anything 
    chunks = ParseLargeUploadChunks(responseJObject, _10MB, length); 
} 
while (chunks.Count > 0);//keep going until no chunks left 

すべてはコメントが何を言うんや名前が示唆するものを、メソッドやクラスの多くは私のものですから、明白ではないかもしれないことを説明するのはうれしいです。

私は何が起こっているのか全く分からず、助けていただければ幸いです。私は土曜日に学校に戻る前にこれをやろうとしており、もはやそれに取り組む時間はありません。

EDIT:しばらく待ってから、PostMan経由でアップロードURLを再度リクエストすることができます。

EDIT 2:私はもはやこのタイムアウト現象を郵便配達員に複製することはできません。アプリケーションからアップロードURLを取得したか、別のPostmanリクエストから取得したものであっても、アップロードがアプリケーションで停止しているかどうかに関わらず、私は郵便配達ですべてのフラグメントをアップロードすることができます。

EDIT 3:この応答しない動作は、コンテンツストリームを読み込む前に開始されます。

編集4: WireSharkのパケット情報を見ると、最初の2つのチャンクはほぼ同じですが、 "再送"パケットだけが3番目に表示されます。

答えて

0

さまざまなレベルのテストを3週間行った結果、私は最終的に問題を把握し、OneDrive Graph APIとはほとんど関係がありません。問題は、Httpリクエストを作成するときに、HttpCompletionOption.ResponseHeadersReadを使用していましたが、次のリクエストを送信する前にレスポンスを読んでいないことでした。これは、HttpClientが私が古いものからの応答を読むまで、私がより多くの要求を送ることを妨げていたことを意味します。ロックされる前に2つのリクエストを送ることができたので奇妙でした。

関連する問題