I am trying to open a FileSaveDialog and when the user presses save, I am creating a zip in the LocalFolder and moving it over to the user selected location. With this code, the file successfully moves to the selected location, but I get an exception like 'Value does not fall within the expected range error.' when I say var storageFolder = await StorageFolder.GetFolderFromPathAsync(localfile.Path);
Please help.
Here is the full code.
public async Task<bool> WriteFilesToFolder(string baseFolderName, Dictionary<string, string> contentOfFilesWithFileNames)
{
try
{
var savePicker = new FileSavePicker();
savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
// Dropdown of file types the user can save the file as
savePicker.FileTypeChoices.Add("zip", new List<string>() { ".zip" });
// Default file name if the user does not type one in or select a file to replace
savePicker.SuggestedFileName = baseFolderName;
StorageFile localfile = await savePicker.PickSaveFileAsync();
if (localfile == null)
{
return false;
}
string pathOfZip = string.Empty;
StorageFolder destinationfolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(baseFolderName, CreationCollisionOption.ReplaceExisting);
if (destinationfolder != null)
{
StorageApplicationPermissions.FutureAccessList.AddOrReplace("PickedFolderToken", destinationfolder);
for (int i = 0; i < contentOfFilesWithFileNames.Count; i++)
{
var item = contentOfFilesWithFileNames.ElementAt(i);
string fileNameToCreate = item.Key;
string formattedFileName = fileNameToCreate.Replace(",", string.Empty).Replace("/", "-").Replace(":", "-");
var file = await destinationfolder.CreateFileAsync(string.Format("{0}.html", formattedFileName), CreationCollisionOption.ReplaceExisting);
var res = await WriteStorageFileAction(file, item.Value);
}
await Task.Run(() =>
{
string temp = Directory.GetParent(destinationfolder.Path).FullName;
pathOfZip = string.Format("{0}\\{1}{2}.zip", temp, baseFolderName, DateTime.Now.ToString("yyyy-MM-dd_hh-mm"));
if (File.Exists(pathOfZip))
{
File.Delete(pathOfZip);
}
// Zipping file into the same folder throws exception that its being used by an other process.
// So zip to new location.
ZipFile.CreateFromDirectory(destinationfolder.Path, pathOfZip,
CompressionLevel.Optimal, true);
});
if (localfile != null)
{
string faToken = StorageApplicationPermissions.FutureAccessList.Add(localfile);
StorageFile file = await StorageFile.GetFileFromPathAsync(pathOfZip);
var storageFolder = await StorageFolder.GetFolderFromPathAsync(localfile.Path); //This line throws the exception.
await file.MoveAsync(storageFolder);
}
await destinationfolder.DeleteAsync();
return true;
}
}
catch (Exception ex)
{
throw;
}
return false;
}
Update:
Here is the Mainifest Namespaces:
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap mp rescap">
I updated the Package Manifest file which looks as follows. but I have a green scribbly under rescap:Capability .
If you want to get a StorageFolder object using
StorageFolder.GetFolderFromPathAsync
method, then you need to pass a folder path as parameter. Thelocalfile
object is a StorageFile object that you got from a FileSavePicker. Thelocalfile.Path
represents a location of a file, not a folder. That's why you are having this exception.For your scenario, if you want to get the parent folder of the file that you've picked, I'd suggest you use StorageFile.GetParentAsync Method
Update:
It seems that you are picking files that are placed somewhere the UWP app doesn't have permissions to access by default. So the picker could only give you access to the single file but you can't achieve the parent folder because you don't have permission to access the folder.
Please go through File access permissions to understand this behavior better.
For such a scenario, if you want to get the parent folder that places somewhere the UWP doesn't have permission to access. using the path will be better. First, you will need to add the
broadFileSystemAccess
capability in the manifest file.Like this:
Then, after you've got the
localfile
object, split the path of thelocalfile
and you could get the path of the parent folder.Now you could call
StorageFolder.GetFolderFromPathAsync
like this: