I'm trying to add multiple files to an already created ZIP file using PickMultipleFilesAsync(). I previously created the ZIP file I want to access in the same code using FilesavePicker.PickSaveFileAsync() method. The app is running on Windows 10 Pro version 1803 in Laptop PC, and I used Visual Studio Community 2017 to create it.
The problem I get is that, after following steps described in the FileOpenPicker MSDN page, I get a System.UnauthorizedAccessException: 'Access to the path 'C:\Users\'User'\Downloads{ZIP file}' is denied.'
I created ZIP file and tried to add new files using this code:
StorageFile file = await savePicker.PickSaveFileAsync();
if (file != null)
{
// Prevent updates to the remote version of the file until we finish making changes and call CompleteUpdatesAsync.
CachedFileManager.DeferUpdates(file);
try
{
Stream stream = await file.OpenStreamForWriteAsync();
using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Update))
{
// This line works fine, file is added
archive.CreateEntryFromFile(path_to_another_file, file_name_in_ZIP);
//....
var dialog = new MessageDialog("Do you want to add more files to ZIP?");
//... (dialog configuration for Yes/No options)
var result = await dialog.ShowAsync();
if(result.Label == "Yes")
{
Debug.WriteLine("Yes option was selected!");
// Include additional files
var openPicker = new FileOpenPicker();
openPicker.FileTypeFilter.Add("*");
openPicker.SuggestedStartLocation = PickerLocationId.Downloads;
IReadOnlyList<StorageFile> addedFiles = await openPicker.PickMultipleFilesAsync();
if (addedFiles.Count > 0)
{
// Application now has read/write access to the picked file(s)
foreach (StorageFile addedFile in addedFiles)
{
Debug.WriteLine(addedFile.Path); // No problem here
// I get the UnauthorizedAccessException here:
archive.CreateEntryFromFile(addedFile.Path, #"additional files/" + addedFile.Name);
}
}
else
{
// Update log file
globalLog += GetTime() + "No additional files";
}
}
}
}
}
I already added <rescap:Capability Name="broadFileSystemAccess"/> to appxmanifest just in case, but as I had access to selected files using FileOpenPicker I think that is not the problem.
As I created the ZIP file within this code I should still have access to it, right? I suspect that FileOpenPicker somehow "closes" access to ZIP file in order to give access to files to be added, or that MessageDialog prevents of accessing the ZIP file I created after I called showAsync().
Is there any other way to achieve what I'm trying?
EDIT: I can not access the file(s) I select using FileOpenPicker, despite I can show file name(s) in Debug console. ZIP file access is OK.
I just found a solution. As stated here, you can use a buffer to stream file contents to ZIP file, just replace:
// I get the UnauthorizedAccessException here:
archive.CreateEntryFromFile(addedFile.Path, #"additional files/" + addedFile.Name);
With:
ZipArchiveEntry readmeEntry = archive.CreateEntry(#"additional files/" + addedFile.Name);
byte[] buffer = WindowsRuntimeBufferExtensions.ToArray(await FileIO.ReadBufferAsync(addedFile));
using (Stream entryStream = readmeEntry.Open())
{
await entryStream.WriteAsync(buffer, 0, buffer.Length);
}
That way, files are added and no UnauthorizedAccessException happens. Hope this helps anyone with the same problem!
Related
I'm creating an UWP application to split CSV and Excel files. The user has to select a file in any folder on the machine and the application has to read the file. At the end of the process, the application has to save one or more files based on what the user wants.
When I try to read a CSV file with this code
using (var reader = new StreamReader(file))
using (var csv = new CsvReader(reader, config))
{
return csv.GetRecords<dynamic>();
}
I receive an error
System.UnauthorizedAccessException: 'Access to the path 'C:\Users\enric\Downloads\combined_data.csv' is denied.'
I checked the capabilities in the Package.appxmanifest but there is none related to files or folders. There is only Removable Storage that seems similar to what I'm looking for but it doesn't work.
In the Microsoft documentation, I read to add a custom capability
<Capabilities><uap:Capability Name="documentsLibrary"/></Capabilities>
but it doesn't work either.
You don't need to specify capabilities, just use pick file or read file code, this code can be also found in Microsoft doc and doc.
private async void Btn_OpenFile_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
try
{
FileOpenPicker picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".csv");
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
var file = await picker.PickSingleFileAsync();
if (file != null)
{
}
}
catch
{
}
}
I have the following lines of code that work for creating a zip using ZipFile.CreateFromDirectory(selectedFile, zipPath)
if (selectedFolder == string.Empty)
{
Console.WriteLine("Invalid folder, try again");
}
else
{
Console.WriteLine("\nSelect zipfile name: ");
var zipName = Console.ReadLine();
// Also available: extractToDirectory
var zipPath = #"C:\Users\User\Documents\Dev\" + zipName + ".zip";
ZipFile.CreateFromDirectory(selectedFolder, zipPath);
However, the following code which should for all intents and purposes do the same thing except for multiple files being archived into a single zip folder refuses to work:
public static void CreateZipFile(string folderToCreateZip, IEnumerable<string> files)
{
var zipPath = folderToCreateZip + "\\test6.zip";
// Create a new ZIP in this location
using (var zip = ZipFile.Open(zipPath, ZipArchiveMode.Create))
{
foreach (var file in files)
{
// Add entry for files
zip.CreateEntryFromFile(file, zipPath, CompressionLevel.Optimal);
}
}
// Dispose of zip object after files have been zipped
//zip.Dispose();
}
var zip == ZipArchive zip
I've tried disabling read-only mode on the folders where the zip should get created, but I don't think this matters since the prior function with CreateFromDirectory() works fine. I've also tried creating a ZIP on desktop, but I get the same error.
This is the exception I'm getting:
As a note, I noticed that it does initially create the zip despite this error, just that it cannot add anything to it unlike CreateFromDirectory() can due to the folder either being in use, no permissions to that area or the folder already existing. Is there a way I can get CreateEntryFromFile() working or an alternative that would work for multiple files?
I had the same problem. The solution was post the full path name at the destinationArchiveFileName parameter (and also a write alowed path). For example c:\my apps folder\my app\my temp\zipfile.zip
I'm trying to create a file explorer for windows 10 mobile
I need to launch files with default app from pathes (not installed directory)
ex. "d:\test.pdf"
Here's what I've tried:
string p = #"a.jpg";
StorageFolder externalDevices = Windows.Storage.KnownFolders.RemovableDevices;
StorageFile file = await externalDevices.GetFileAsync(p);
var success = await Launcher.LaunchFileAsync(fff);
you can use Windows.System.Launcher API to launch the default handler for a file you can read more here
async void DefaultLaunch()
{
// Path to the file in the app package to launch
string imageFile = #"images\test.png";
var file = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(imageFile);
if (file != null)
{
// Launch the retrieved file
var success = await Windows.System.Launcher.LaunchFileAsync(file);
if (success)
{
// File launched
}
else
{
// File launch failed
}
}
else
{
// Could not find file
}
}
If you want to access files from SD card, please make sure that you have read the What you can and can't access on the SD card section on document.
Your app can only read and write files of file types that the app has registered to handle in the app manifest file.
Your app can also create and manage folders.
Make sure that you check "Removable Storage" in the capabilities of the appxmanifest.
You must declare a file type association in the Package.appxmanifest in order to read files from the SD card. The following is an example of one that I set up:
Then, I used the following code sample to launch a picture which is contained in "New folder" on SD card successfully.
string p = #"1.jpg";
StorageFolder externalDevices = Windows.Storage.KnownFolders.RemovableDevices;
var rootfolder = (await externalDevices.GetFoldersAsync()).FirstOrDefault();
var folder = await rootfolder.GetFolderAsync("New folder");
var file = await folder.GetFileAsync(p);
var success = await Launcher.LaunchFileAsync(file);
I'm trying to make a UWP app which can export a file saved in his own storage into the document library.
In Package.appxmanifest I've inserted the following lines:
<uap:Capability Name="picturesLibrary" />
<uap:Capability Name="documentsLibrary" />
The code to get the path is this:
StorageFolder storageFolder = await KnownFolders.GetFolderForUserAsync(null /* current user */, KnownFolderId.DocumentsLibrary);
string path = storageFolder.Path + "\\" + fileName;
The code to save the file is this:
FileStream writer = new FileStream(filePath, FileMode.Create);
At this point, the program launches this exception:
Access to the path 'C:\Users\luca9\AppData\Roaming\Microsoft\Windows\Libraries\Documents.library-ms' is denied.
On my 950XL, the exception is similar:
Access to the path 'C:\Data\Users\DefApps\APPDATA\ROAMING\MICROSOFT\WINDOWS\Libraries\Documents.library-ms' is denied.
I've tryied both on Documents and Pictures libraries, but I get the same exception.
How can I solve it?
Thank you in advance,
Luca
Don't get FileStream with path - the app doesn't have privileges. As you already have StorageFolder, use it to create a StorageFile and then get stream from it with one of its methods, for example:
var file = await storageFolder.CreateFileAsync("fileName");
using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
// do what you want
}
this example from Microsoft works with uwp.
https://learn.microsoft.com/en-us/windows/uwp/files/quickstart-save-a-file-with-a-picker
1. Create and customize the FileSavePicker
var savePicker = new Windows.Storage.Pickers.FileSavePicker();
savePicker.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary;
// Dropdown of file types the user can save the file as
savePicker.FileTypeChoices.Add("Plain Text", new List<string>() { ".txt" });
// Default file name if the user does not type one in or select a file to replace
savePicker.SuggestedFileName = "New Document";
2. Show the FileSavePicker and save to the picked file
Windows.Storage.StorageFile file = await savePicker.PickSaveFileAsync();
if (file != null)
{
// Prevent updates to the remote version of the file until
// we finish making changes and call CompleteUpdatesAsync.
Windows.Storage.CachedFileManager.DeferUpdates(file);
// write to file
await Windows.Storage.FileIO.WriteTextAsync(file, file.Name);
// Let Windows know that we're finished changing the file so
// the other app can update the remote version of the file.
// Completing updates may require Windows to ask for user input.
Windows.Storage.Provider.FileUpdateStatus status =
await Windows.Storage.CachedFileManager.CompleteUpdatesAsync(file);
if (status == Windows.Storage.Provider.FileUpdateStatus.Complete)
{
this.textBlock.Text = "File " + file.Name + " was saved.";
}
else
{
this.textBlock.Text = "File " + file.Name + " couldn't be saved.";
}
}
else
{
this.textBlock.Text = "Operation cancelled.";
}
I'm trying to read data from json file in .NET 4.5 for Windows Phone app. After pressing button the exception appears saying:
System.IO.FileNotFoundException (Exception from HRESULT: 0x80070002)
My code:
public static async Task ReadFile()
{
StorageFolder local = Windows.ApplicationModel.Package.Current.InstalledLocation;
if (local != null)
{
var file = await local.OpenStreamForReadAsync("bazaDanych.json");
using (StreamReader streamReader = new StreamReader(file))
{
json = streamReader.ReadToEnd();
}
}
}
Here's my view of Solution Explorer:
You're not copying your file to the local storage.
Put your json file under the Assets folder, make sure that it's properties says "Content" and "Copy Always"
On the first launch you should read the json from the package
var filename = "Assets/BazaDanych.json";
var sFile = await StorageFile.GetFileFromPathAsync(filename);
var fileStream = await sFile.OpenStreamForReadAsync();
And store into the local storage.
There is an example for Windows 8 (which is more or less the same)
Related question.