是否可以将UWP StorageFile拖放到桌面,使用CreateStreamedFileFromUriAsyc创建

时间:2017-09-20 03:10:43

标签: winapi drag-and-drop uwp storagefile

目标: 我想要做的是将GridViewItem从应用程序的外部的UWP应用 GridView拖到桌面浏览器。在放置事件期间,我想从互联网上下载文件并创建一个StorageFile,用于填充DataPackage。我希望将此StorageFile复制到桌面。不幸的是,当UWP Drag& Drop(使用SetDataProvider)使用延期时,只要您离开应用程序窗口,请求就会被激活,您必须使用该对象填充DataPackage转移。所以,在我看来,我需要使用StorageFile创建的延迟类型CreateStreamedFileFromUriAsyc

每次我开始执行拖放操作时,我都不想预先下载数据。我只是想在我将它放到合法复制的地方时下载数据。

App in action showing a file being dragged to the desktop.

  1. 我知道如何使用延迟请求将预先存在的StorageFile从UWP拖放到资源管理器(桌面)。
  2. 我也知道如何使用StorageFile创建一个CreateStreamedFileFromUriAsyc,它会为您提供仅在请求数据时下载数据的StorageFile
  3. 当我尝试将这两个想法结合起来时,Windows资源管理器会给我错误'界面不受支持'。

    如果我使用完全相同的代码,但只是在延迟拖动处理程序中通过调用类似GetBasicPropertiesAsync的内容来获取文件内容,则仅当我在桌面上按住拖动直到下载文件时它才有效。当拖动图标从“禁止”图标变为“复制”时,我可以看到它完成。如果我在完成之前松开鼠标按钮,则不会发生任何复制,也不会出现错误。

    显然,我希望拖放下载而不必在延迟处理程序上手动启动它。有任何想法吗?这可能吗?

    (是的,我意识到创建正确文件扩展名的代码是错误的/不完整的,但这与此无关......)

    //DragStarted Handler in constructor
    DragItemsStartedCommand = ReactiveCommand.Create<DragItemsStartingEventArgs>((e) =>
            {
                _dragItems = e.Items.Cast<ItemViewModel>();
                e.Data.Properties.Title = "Transfer file";
                e.Data.Properties.Description = "desscription of transfering a file";
                e.Data.Properties.FileTypes.Add(StandardDataFormats.StorageItems);
                e.Data.SetDataProvider(Windows.ApplicationModel.DataTransfer.StandardDataFormats.StorageItems, OnDeferredStorageFileRequestedHandler);
                e.Data.RequestedOperation = DataPackageOperation.Copy;
            });
    
    
     //Deferred request handler
        async void OnDeferredStorageFileRequestedHandler(DataProviderRequest request)
        {
            DataProviderDeferral deferral = request.GetDeferral();
            try
            {
                Task<IEnumerable<StorageFile>> task = null;
                await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
                {
                    task = DownloadStorageFiles();
                });
                var result = await task;
                request.SetData(result);
            }
    
            catch (Exception ex)
            {
                // Handle the exception
            }
    
            finally
            {
                deferral.Complete();
                Debug.WriteLine("deferral complete!!!");
            }
    
        }
    
    //Create StorageFile with deferred loading Task
        async Task<IEnumerable<StorageFile>> DownloadStorageFiles()
        {
            List<StorageFile> storageItems = new List<StorageFile>();
            foreach (var item in _dragItems)
            {
                var request = new RestSharp.RestRequest();
            var defaultItemType = ItemType.MSWord;
            switch (item.MimeTypeTranslated)
            {
                case ItemType.GoogleDocument:
                case ItemType.GoogleSpreadsheet:
                case ItemType.GooglePresentation:
                case ItemType.GoogleDrawing:
                case ItemType.GoogleScript:
                    request.Resource = $"files/{item.File.id}/export";
                    request.AddParameter("mimeType", Statics.ItemTypeDictionary.First(x => x.Value == defaultItemType).Key);
                    break;
                default:
                    request.Resource = $"files/{item.File.id}";
                    request.AddParameter("alt", "media");
                    break;
            }
            string fileName = "";
            if (item.File.name.EndsWith($".{Statics.ItemExtensionDictionary[defaultItemType]}"))
                fileName = $"{item.File.name}";
            else
                fileName = $"{item.File.name}.{Statics.ItemExtensionDictionary[defaultItemType]}";
            var uri = account.Client.GetAuthorizedUriForDownload(request);
    
            var thumbnail = RandomAccessStreamReference.CreateFromFile(await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///StoreLogo.png")));
            var storageFileDeferred = await StorageFile.CreateStreamedFileFromUriAsync(fileName, uri , thumbnail);
            //var props = await storageFileDeferred.GetBasicPropertiesAsync();                
             storageItems.Add(file);
            }
            return storageItems;
        }
    

    GitHub重现这个问题: https://github.com/limefrogyank/DragDeferredFileToDesktop

    1. 第一页是定期拖动到桌面,因为StorageFile(+基础数据)已经在资产文件夹中
    2. 第二页显示使用通过CreateStreamedFileFromUriAsync创建的StorageFile时生成的错误。
    3. 第三页使用相同类型的StorageFile,但有一个hack强制同步检索数据。桌面冻结一秒钟,直到数据准备就绪。

1 个答案:

答案 0 :(得分:0)

从最近的Windows更新开始,系统会自动处理UWP应用程序上存储文件的拖放操作。

example gif.