FileOpenPicker в HoloLens предоставляет неполный файл из OneDrive
Я использую FileOpenPicker для выбора файла из OneDrive, к которому я впоследствии буду обращаться через «стандартные» интерфейсы C++ (не C++/WinRT). Я знаю, что путь, возвращаемый FileOpenPicker, недоступен для этих интерфейсов, поэтому я использую StorageFile::CopyAsync для копирования файла в доступное место в ApplicationData.
Это работает в сборке UWP x64 на рабочем столе, но не работает в сборке UWP arm64 на HoloLens 2.
В HoloLens FileOpenPicker предоставляет лишь небольшую часть файла. Например, из файла размером 2,83 МБ в OneDrive FileOpenPicker и CopyAsync создают файл размером всего 144,6 КБ. Я провел тесты на размер и полноту файла как для исходного файла, предоставленного FileOpenPicker, так и для целевого файла для CopyAsync, например:
uint64_t sourceSize = sourceFile.GetBasicPropertiesAsync().get().Size();
bool sourceIncomplete
= uint32_t (sourceFile.Attributes())
& uint32_t (FileAttributes::LocallyIncomplete);
Бит LocallyIncomplete сброшен, хотя размер составляет всего 144,6 КБ из 2,83 МБ.
Затем CopyAsync успешно копирует предоставленные ему 144,6 КБ, но позже происходит сбой, поскольку исходный файл из FileOpenPicker является неполным и недействительным.
Чего мне не хватает для HoloLens 2?
Вот минимальный воспроизводимый пример — небольшая модификация Scenario1_SingleFile.cpp из образца Microsoft GitHub FilePicker по адресу https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/FilePicker/cppwinrt .
Скомпилируйте для 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.");
}
}
}