从OneDrive下载后无法立即打开文件

时间:2014-12-22 10:27:33

标签: c# windows onedrive

在Windows 8.1下成功从OneDrive下载JPG文件后,我无法打开它并立即将该流用作图像源。相反,我的应用程序必须在等待循环中运行才能重试打开,直到异常“错误HRESULT E_FAIL已从调用COM组件返回”不再发生。或者应用程序必须通知用户重试该操作。大约一秒左右后,可以打开文件,流可以用作图像源。如果JPG文件最初不能脱机使用并且我的应用程序下载它,则会出现此问题。我想知道是否有人有更好的解决方案来解决这个问题。以下是我的一些代码:

private async void LoadFileButton_Click(object sender, RoutedEventArgs e)
    {
        FileOpenPicker picker = new FileOpenPicker();
        picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
        picker.ViewMode = PickerViewMode.Thumbnail;
        picker.FileTypeFilter.Add(".png");
        picker.FileTypeFilter.Add(".jpe");
        picker.FileTypeFilter.Add(".jpeg");
        picker.FileTypeFilter.Add(".jpg");
        picker.FileTypeFilter.Add(".gif");

        Stream stream = null;
        StorageFile file = await picker.PickSingleFileAsync();
        if (file != null)
        {
            var basicProperties = await file.GetBasicPropertiesAsync();
            var props = await basicProperties.RetrievePropertiesAsync(
                              new string[] { "System.OfflineAvailability", "System.StorageProviderFileRemoteUri" });
            if (props.ContainsKey("System.OfflineAvailability"))
            {
                var offline = (uint)props["System.OfflineAvailability"];
                if (offline == 0)
                {
                    if (file.Provider.DisplayName == "OneDrive")
                    {
                        if (props.ContainsKey("System.StorageProviderFileRemoteUri"))
                        {
                            var uri = (string)props["System.StorageProviderFileRemoteUri"];
                            var res = await GameStorage.DownloadOneDriveFile(file, uri, _downloadProgressBar);
                            if (res is string)
                            {
                                await App.InformUserAsync(res.ToString(), _title.Text);
                                return;
                            }
                            stream = (Stream)res;
                        }
                    }
                    else
                    {
                        await App.InformUserAsync(String.Format(
                                App.GetString("MakeFileOfflinePrompt", "GameManagement"),
                                file.Path), _title.Text);
                        return;
                    }
                } 
            }
            if (stream == null)
            {
                stream = await file.OpenStreamForReadAsync();
            }
            await _photoClipper.SetDisplayImageStreamAsync(stream);
            _clipPhotoButton.IsEnabled = true;
        }
    }
internal static async Task<object> DownloadOneDriveFile(StorageFile file, string url, 
                                                            ProgressBar progressBar = null)
    {
        if (progressBar != null)
        {
            progressBar.Visibility = Visibility.Visible;
            progressBar.Value = 1;
        }
        if (__liveClient == null)
        {
            var msg = await ConnectLive();
            if (!String.IsNullOrEmpty(msg))
            {
                return msg;
            }
        }
        var uri = new Uri(WebUtility.UrlDecode(url));
        var pathElements = uri.LocalPath.Split(new char[] { '/' }, 
                                               StringSplitOptions.RemoveEmptyEntries);
        var parentId = "folder." + pathElements[0];
        IDictionary<string, object> props = null;

        for (var i = 1; i < pathElements.Length; i++)
        {
            props = await FindOneDrivePathElement(parentId, pathElements[i]);
            if (props == null)
            {
                return String.Format(App.GetString("OneDrivePathElementNotFound", 
                                     "GameManagement"), pathElements[i], uri);
            }
            parentId = props["id"].ToString();
            if (progressBar != null) progressBar.Value += 1;
        }
        try
        {
            var operation = await __liveClient.CreateBackgroundDownloadAsync(parentId + 
                                               "/content", file);
            LiveDownloadOperationResult result = null;

            if (progressBar != null)
            {
                progressBar.Value = 10;
                var progressHandler = new Progress<LiveOperationProgress>(
                    (progress) => { progressBar.Value = progress.ProgressPercentage; });
                var cts = new CancellationTokenSource();
                result = await operation.StartAsync(cts.Token, progressHandler);
            }
            else
            {
                result = await operation.StartAsync();
            }
            var trialsCount = 0;
            string openErr = null;
            Stream stream = null;

            while (trialsCount < 5)
            {
                try
                {
                    stream = await result.File.OpenStreamForReadAsync();
                    break;
                }
                catch (Exception ex)
                {
                    openErr = ex.Message; 
                }
                trialsCount += 1;
                await App.SuspendAsync(1000);
            }
            if (stream != null)
            {
                return stream;
            }
            return String.Format(App.GetString("OneDriveCannotOpenDownloadedFile", 
                                               "GameManagement"), file.Path, openErr);
        }
        catch (Exception ex)
        {
            return String.Format(App.GetString("OneDriveCannotDownloadFile",
                                               "GameManagement"), file.Path, ex.Message);
        }
        finally
        {
            if (progressBar != null)
            {
                progressBar.Visibility = Visibility.Collapsed;
            }
        }
    }
private static async Task<IDictionary<string, object>> FindOneDrivePathElement(
                                                           string parentId, string childName)
    {
        var res = await __liveClient.GetAsync(parentId + "/files");

        if (res.Result.ContainsKey("data"))
        {
            var items = (IList<object>)res.Result["data"];

            foreach (var item in items)
            {
                var props = (IDictionary<string, object>)item;
                if (props.ContainsKey("name"))
                {
                    var name = props["name"].ToString();
                    if (name == childName)
                    {
                        if (props.ContainsKey("id"))
                        {
                            return props;
                        }
                    }
                }
            }
        }
        return null;
    }

1 个答案:

答案 0 :(得分:0)

我再次尝试打开“可用的在线”文件,并且奇迹般的“错误HRESULT E_FAIL”不再发生。出于何种原因,我不知道。但是,我真的不需要自己处理这种情况。感谢。