【问题标题】:Can't download complete image file from skydrive using REST API无法使用 REST API 从 skydrive 下载完整的图像文件
【发布时间】:2012-05-02 11:10:50
【问题描述】:

我正在为 C# 中的 skydrive API 开发一个快速包装器,但在下载文件时遇到了问题。对于文件的第一部分,一切正常,但随后文件开始出现差异,此后不久一切都变为空。我很确定只是我没有正确读取流。

这是我用来下载文件的代码:

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;
}

这是我要下载的图片文件

这是我得到的图像

这两张图片让我相信我不会等待响应完成,因为内容长度与我期望的图片大小相同,但我不确定如何让我的代码等待整个响应通过,甚至如果这是我需要采取的方法。

这是我的测试代码,以防有用

[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);
}

它在Assert.IsTrue(sameData); 失败

【问题讨论】:

标签: c# webresponse onedrive


【解决方案1】:

这是因为您没有检查responseStream.Read(contents, 0, (int)response.ContentLength); 的返回值。 Read 不能确保它会读取 response.ContentLength 字节。相反,它返回读取的字节数。你可以在那里使用循环或stream.CopyTo

类似这样的:

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

【讨论】:

    【解决方案2】:

    正如 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();
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-02
      • 1970-01-01
      • 2013-05-13
      • 1970-01-01
      • 2022-12-15
      • 2018-01-09
      • 2021-11-16
      • 1970-01-01
      相关资源
      最近更新 更多