我正在使用 FileOpenPicker 从 OneDrive 中选择一个文件,随后我将通过“标准”C++ 接口(不是 C++/WinRT)访问该文件。我知道这些接口无法访问 FileOpenPicker 返回的路径,因此我使用 StorageFile::CopyAsync 将文件复制到 ApplicationData 下的可访问位置。
这适用于桌面上的 UWP x64 构建,但在 HoloLens 2 上的 UWP arm64 构建中失败。
在 HoloLens 上,FileOpenPicker 仅提供文件的一小部分。例如,对于 OneDrive 上 2.83 MB 的文件,FileOpenPicker 和 CopyAsync 生成的文件只有 144.6 KB。我已经对 FileOpenPicker 提供的源文件和 CopyAsync 的目标文件的文件大小和完整性进行了测试——例如:
uint64_t sourceSize = sourceFile.GetBasicPropertiesAsync().get().Size();
bool sourceIncomplete
= uint32_t (sourceFile.Attributes())
& uint32_t (FileAttributes::LocallyIncomplete);
LocallyIncomplete 位是明确的,即使大小仅为 2.83 MB 中的 144.6 KB。
CopyAsync 然后成功地复制了它所提供的 144.6 KB,但后来由于 FileOpenPicker 中的源文件不完整且无效而失败。
HoloLens 2 缺少什么?
这是一个最小的可重现示例——从https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/FilePicker/cppwinrt的 Microsoft GitHub FilePicker 示例中对 Scenario1_SingleFile.cpp 稍作修改
为 UWP-arm64 编译,部署到 HoloLens 2,并在 OneDrive 上使用数兆字节的文件进行测试。
// Modified version of Scenario1_SingleFile.cpp
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************
#include "pch.h"
#include "Scenario1_SingleFile.h"
#include "Scenario1_SingleFile.g.cpp"
#include <winrt/Windows.Storage.FileProperties.h>
#include <sstream>
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Storage;
using namespace Windows::Storage::Pickers;
using namespace Windows::UI::Xaml;
namespace winrt::SDKTemplate::implementation
{
Scenario1_SingleFile::Scenario1_SingleFile()
{
InitializeComponent();
}
fire_and_forget Scenario1_SingleFile::PickAFileButton_Click(IInspectable const&, RoutedEventArgs const&)
{
auto lifetime = get_strong();
// Clear previous returned file name, if it exists, between iterations of this scenario
OutputTextBlock().Text(L"");
FileOpenPicker openPicker;
openPicker.ViewMode(PickerViewMode::Thumbnail);
openPicker.SuggestedStartLocation(PickerLocationId::PicturesLibrary);
openPicker.FileTypeFilter().ReplaceAll({ L".jpg", L".jpeg", L".png",
// twhall@umich.edu added for "big" files:
L".mp4", L".wmv", L".stl" });
StorageFile file = co_await openPicker.PickSingleFileAsync();
if (file != nullptr)
{
// Application now has read/write access to the picked file
#if 0
OutputTextBlock().Text(L"Picked photo: " + file.Name());
#else
// twhall@umich.edu:
// * Add feedback for file size and incompleteness.
// * Test on multi-megabyte files picked from OneDrive
// on the HoloLens (UWP-arm64)
auto props = co_await file.GetBasicPropertiesAsync();
uint64_t size = props.Size();
uint32_t incomplete = (
uint32_t (file.Attributes()) &
uint32_t (FileAttributes::LocallyIncomplete));
std::wstringstream text{};
text << L"Picked file: " << file.Name().c_str()
<< L" (" << size << L" bytes, "
<< (incomplete ? L"incomplete)" : L"complete)");
OutputTextBlock().Text(text.str().c_str());
#endif
}
else
{
OutputTextBlock().Text(L"Operation cancelled.");
}
}
}