I'm using the FileOpenPicker to select a file from OneDrive, that I will subsequently access through "standard" C++ interfaces (not C++/WinRT). I'm aware that the path returned by FileOpenPicker is not accessible by those interfaces, so I'm using StorageFile::CopyAsync to copy the file to an accessible location under the ApplicationData.
This works in a UWP x64 build on the desktop, but fails in a UWP arm64 build on the HoloLens 2.
On the HoloLens, the FileOpenPicker is providing only a small fraction of the file. For example, from a file that is 2.83 MB on OneDrive, the FileOpenPicker and CopyAsync are producing a file of only 144.6 KB. I've put in tests for the file size and completeness for both the source file provided by the FileOpenPicker and the destination file for CopyAsync -- e.g.:
uint64_t sourceSize = sourceFile.GetBasicPropertiesAsync().get().Size();
bool sourceIncomplete
= uint32_t (sourceFile.Attributes())
& uint32_t (FileAttributes::LocallyIncomplete);
The LocallyIncomplete bit is clear, even though the size is only 144.6 KB out of 2.83 MB.
CopyAsync then successfully copies the 144.6 KB that it was given, but stuff fails later because the source file from the FileOpenPicker is incomplete and invalid.
What am I missing for the HoloLens 2?
Here is a minimal reproducible example -- a slight modification of Scenario1_SingleFile.cpp from the Microsoft GitHub FilePicker sample at https://github.com/microsoft/Windows-universal-samples/tree/master/Samples/FilePicker/cppwinrt
Compile for UWP-arm64, deploy to HoloLens 2, and test with multi-megabyte files on 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",
// [email protected] 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
// [email protected]:
// * 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.");
}
}
}