2012-05-01 5 views
1

私はC#のskydrive APIのクイックラッパーを使用していますが、ファイルのダウンロードに関する問題に取り組んでいます。ファイルの最初の部分についてはすべてがうまくいっていますが、ファイルの相違が始まるとすぐにすべてがnullになります。私はちょうど私がストリームを正しく読んでいないことはかなり確信しています。REST APIを使用してskydriveから完全なイメージファイルをダウンロードできません

これは私がファイルをダウンロードするために使用しているコードです:

public const string ApiVersion = "v5.0"; 
public const string BaseUrl = "https://apis.live.net/" + ApiVersion + "/"; 

public SkyDriveFile DownloadFile(SkyDriveFile file) 
{ 
    string uri = BaseUrl + file.ID + "/content"; 
    byte[] contents = GetResponse(uri); 
    file.Contents = contents; 
    return file; 
} 

public byte[] GetResponse(string url) 
{ 
    checkToken(); 
    Uri requestUri = new Uri(url + "?access_token=" + HttpUtility.UrlEncode(token.AccessToken)); 
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri); 
    request.Method = WebRequestMethods.Http.Get; 
    WebResponse response = request.GetResponse(); 
    Stream responseStream = response.GetResponseStream(); 
    byte[] contents = new byte[response.ContentLength]; 
    responseStream.Read(contents, 0, (int)response.ContentLength); 
    return contents; 
} 

は、これは私が

The Correct Image

をダウンロードしようとしている画像ファイルであり、これは画像Iであります午前:

Broken Image

これらの2つのイメージは、コンテンツの長さが予想されるイメージのサイズと同じであるため、応答が完了するのを待っているとは思えませんが、私のコードは応答全体が出てくるのを待つか、それとももし私が取る必要があるアプローチであれば本当にです。

はここで、それはあなたがresponseStream.Read(contents, 0, (int)response.ContentLength);の戻り値をチェックしないためですAssert.IsTrue(sameData);

+0

代わりにWebクライアントを使用しましたか? http://msdn.microsoft.com/en-us/library/ez801hhe.aspx –

答えて

2

[TestMethod] 
public void CanUploadAndDownloadFile() 
{ 
    var api = GetApi(); 
    SkyDriveFolder folder = api.CreateFolder(null, "TestFolder", "Test Folder"); 
    SkyDriveFile file = api.UploadFile(folder, TestImageFile, "TestImage.png"); 
    file = api.DownloadFile(file); 
    api.DeleteFolder(folder); 
    byte[] contents = new byte[new FileInfo(TestImageFile).Length]; 
    using (FileStream fstream = new FileStream(TestImageFile, FileMode.Open)) 
    { 
     fstream.Read(contents, 0, contents.Length); 
    } 
    using (FileStream fstream = new FileStream(TestImageFile + "2", FileMode.CreateNew)) 
    { 
     fstream.Write(file.Contents, 0, file.Contents.Length); 
    } 
    Assert.AreEqual(contents.Length, file.Contents.Length); 
    bool sameData = true; 
    for (int i = 0; i < contents.Length && sameData; i++) 
    { 
     sameData = contents[i] == file.Contents[i]; 
    } 
    Assert.IsTrue(sameData); 
} 

それが失敗した便利だ場合、私のテストコードです。 Readは、response.ContentLengthバイトを確実に読み取ることはできません。代わりに、読み込まれたバイト数を返します。あなたはループまたはstream.CopyToを使用することができます。このような

何か:

WebResponse response = request.GetResponse(); 
MemoryStream m = new MemoryStream(); 
response.GetResponseStream().CopyTo(m); 
byte[] contents = m.ToArray(); 
1

LBは、すでに述べたように、あなたは、ストリーム全体を読むまで)(Readを呼び出すために継続する必要があります。

Stream.CopyToはストリーム全体をコピーしますが、期待されるバイト数を確実に読み取るわけではありません。次のメソッドはこれを解決し、指定された長さを読み取らない場合はIOExceptionを発生させます。

public static void Copy(Stream input, Stream output, long length) 
    { 
     byte[] bytes = new byte[65536]; 
     long bytesRead = 0; 
     int len = 0; 
     while (0 != (len = input.Read(bytes, 0, Math.Min(bytes.Length, (int)Math.Min(int.MaxValue, length - bytesRead))))) 
     { 
      output.Write(bytes, 0, len); 
      bytesRead = bytesRead + len; 
     } 
     output.Flush(); 
     if (bytesRead != length) 
      throw new IOException(); 
    } 
関連する問題