iOS Xamarin.iOS损坏了网络下载

时间:2014-01-21 15:51:50

标签: xamarin.ios httpwebrequest corruption

我有一个用Xamarin.iOS编写的应用程序,导致文件在下载到应用程序后被破坏。

我通过下载应用程序中的文件来比较校验和,然后将下载的文件上传到dropbox。然后我将dropbox文件的校验和与服务器上的原始文件进行比较。

通常,校验和匹配。偶尔,校验和不匹配。这些文件实际上是视频,导致视频无法播放。

问题

如何下​​载(使用HttpWebRequest)偶尔会导致文件损坏,但继续成功下载?

守则

public class DownloadService : IDownloadService
{
    private const int BufferSize = 1024*1024;

    /// <summary>
    /// Download a remote file to a local location.
    /// </summary>
    /// <param name="url">The url of the file to download.</param>
    /// <param name="localPath">The local path to save the file.</param>
    /// <param name="progress">The progress off the download (percentage|bytesread|totalbytes).</param>
    /// <param name="cancel">A reference to a boolean that can be set to true if you want to cancel the download.</param>
    /// <returns>
    /// Returns the local file that was downloaded. 
    /// Use this instead of the localPath parameter because you may have passed no extension asking for us to autodetermine the extension.
    /// </returns>
    public string DownloadFile(string url, string localPath, Action<int, long, long> progress, ref bool cancel)
    {
        cancel = false;
        var didCancel = false;
        HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
        webRequest.ReadWriteTimeout = 3000;
        var buffer = new byte[BufferSize];
        var realPath = localPath;

        try
        {
            using (var response = webRequest.GetResponse())
            {
                // get the total size of this request
                var totalSize = 0;
                try { totalSize = int.Parse(response.Headers["MediaItemLength"]);
                }catch(Exception ex) { throw new NotImplementedException("Get the total size some other way!"); }

                // ensure there is a proper extension
                if (string.IsNullOrEmpty(Path.GetExtension(localPath)))
                {
                    // the localpath given didn't have an extension.
                    // we need to try to determine the exention through custom HTTP headers.
                    string httpHeaderExtension = null;
                    try
                    {
                        httpHeaderExtension = response.Headers["MediaExtension"];

                        if (string.IsNullOrEmpty(httpHeaderExtension))
                            throw new Exception("The header was present, but it was empty.");
                    }
                    catch (Exception ex)
                    {
                        throw new Exception("localPath didn't provide an extension and we couldn't infer would through custom HTTP headers.");
                    }

                    // add the correct extension to our local file path
                    realPath += httpHeaderExtension;
                }

                if(File.Exists(realPath))
                    File.Delete(realPath);

                using (var responseStream = response.GetResponseStream())
                {
                    using (var dest = new FileStream(realPath, FileMode.CreateNew, FileAccess.Write))
                    {
                        long totalBytes = 0;
                        int currentBlockSize;

                        while ((currentBlockSize = responseStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            totalBytes += currentBlockSize;
                            var percentage = (int)(totalBytes * 100.0 / totalSize);

                            dest.Write(buffer, 0, currentBlockSize);

                            if (progress != null)
                                progress(percentage, totalBytes, totalSize);

                            if (cancel)
                            {
                                didCancel = true;
                                break;
                            }
                        }
                    }
                }
            }
        }catch(Exception ex)
        {
            // delete the file 
            if (File.Exists(realPath))
                File.Delete(realPath);

            throw;
        }

        // delete the file 
        if (didCancel && File.Exists(realPath))
            File.Delete(realPath);

        return realPath;
    }
}

代码很简单。我确实包含一些额外/自定义标头以获取总文件大小,以便我可以避免HEAD请求获取值。我需要下载进度的总文件大小。

0 个答案:

没有答案