copying and replacing files in uwp - c#

I am creating an app and one of the requirements for the app was to be able to allow the users to change the data that the app has access to by means of changing a folder in the documents folder and pressing an update button. 1. This app will not have access to the internet. 2. Accessing the Documents folder is a specific request(i know uwp is sand-boxed) 3. Essentially I'm trying to moves files from a folder in the documents storage to local storage without the path(since I dont have access to it). This is my attempt at it.
class Copy
{
public async void update()
{
FolderPicker openPicker = new FolderPicker();
openPicker.ViewMode = PickerViewMode.Thumbnail;
openPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".csv");
openPicker.FileTypeFilter.Add(".png");
openPicker.FileTypeFilter.Add(".txt");
StorageFolder updatefolder = await openPicker.PickSingleFolderAsync();
//CreateFileAsync("sample.dat", CreationCollisionOption.ReplaceExisting);
// Do something with the new file.
// Get the app's local folder to use as the destination folder.
StorageFolder mainFolder = ApplicationData.Current.LocalFolder;
// Set options for file type and sort order.
List<string> fileTypeFilter = new List<string>();
fileTypeFilter.Add(".jpg");
fileTypeFilter.Add(".csv");
fileTypeFilter.Add(".png");
fileTypeFilter.Add(".txt");
QueryOptions queryOptions = new QueryOptions(CommonFileQuery.OrderByName, fileTypeFilter);
queryOptions.IndexerOption = IndexerOption.OnlyUseIndexer;
// Get the files in the user's document folder
// and its subfolders and sort them by date.
StorageFileQueryResult results = updatefolder.CreateFileQueryWithOptions(queryOptions);
// Iterate over the results and print the list of files
// to the Visual Studio Output window.
IReadOnlyList<StorageFile> sortedFiles = await results.GetFilesAsync();
sortedFiles.ToList<StorageFile>();
foreach (StorageFile item in sortedFiles)
{
StorageFile copiedFile = await item.CopyAsync(mainFolder, item.DisplayName, NameCollisionOption.ReplaceExisting);
}
}
}
}
This kind of works. When I call the update method, the files copy but don't replace even though I have the CreationCollisionOption.ReplaceExisting option for CreateFileAsync. Also the thumbnails don't transfer over and even though it has the same memory the computer can't recognize what type of file it is. Here is a screenshot.Destination Folder I thought it was due to the list being readonly so I tried explicitly converting it into a list but I received the same result. I'm so close and I just need a little assistance. Any and all help will be greatly appreciated.

Related

Creating Files and Folders in UWP

Ive looked at at so many stackoverflow posts and articles but still didnt manage to create a file in UWP. In WPF it was really easy but UWP works differently.
I added the following in my manifest file:
<Capabilities>
<uap:Capability Name="documentsLibrary" />
</Capabilities>
Now im not sure what to do next. Inside my documents folder I have a subfolder named "Project Files". I want to create folders and files in there. How is this done in UWP? I really dont understand.
As microsoft states in their docs, its recommenced not to use the documents Library through an UWP app, instead opt for the built in storage unless its absolutely necessary.
There is an easy way to get around that if you use a folder picker
private async void buttonClick(){
FolderPicker folderPicker = new FolderPicker();
folderPicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
folderPicker.FileTypeFilter.Add("*");
StorageFolder folder= await folderPicker.PickSingleFolderAsync();
if (folder != null) {
// do Things On Folder
}
else
{
MessageDialog dialog = new MessageDialog("you selected nothing");
await dialog.ShowAsync();
}
}
The above opens up a folder select dialog, it returns the folder the user picked, its the recommended way for accessing locations outside your app's folder.
Here is how to Create a new file in this folder:
string name ="myTitle.txt";
await folder.CreateFileAsync(name, CreationCollisionOption.GenerateUniqueName);
here is how to open and write a file:
try {
StorageFile myFile = await folder.GetFileAsync(name);
await Windows.Storage.FileIO.WriteTextAsync(myFile, "myStringContent");
}
catch (Exception e)
{
Debug.WriteLine("Failure: "+e.Message);
return;
}
remember you can always avoid opening up a dialog if you use the local storage instead, it returns you app's storage folder in one line, like this:
var folder= ApplicationData.Current.LocalFolder;
I believe in UWP using the documents library is neither recommended or permitted. See https://blogs.msdn.microsoft.com/wsdevsol/2013/05/09/dealing-with-documents-how-not-to-use-the-documentslibrary-capability-in-windows-store-apps/
If you side load the app and use the documents library capability the app gets access only to declared file types, not to everything in documents.
See https://msdn.microsoft.com/en-us/library/windows/apps/hh464936.aspx#special_capabilities
Note that this special capability will not let you pass through app certification in Store, unless you go through some special procedure contacting MS first.
To create folder, use StorageFolder. To create file, use StorageFile.
See https://learn.microsoft.com/en-us/windows/uwp/files/quickstart-reading-and-writing-files

UWP c# How to get a StorageFolder object of the app's download folder

I am creating files and folders using DownloadsFolder methods.
I'd like to get the parent folder as a StorageFolder instance so I can list and manipulate all the items in the app's downloads folder.
I've tried GetParentAsync() from a known StorageFile, but the return is null.
StorageFile sf = await DownloadsFolder.CreateFileAsync("testMarker");
StorageFolder dlFolder = await sf.GetParentAsync();
Is there any method to access this folder programmatically?
It seems your app doesn't has permission to read the Downloads directory. We can use GetParentAsync to get a parent the app has permissions for, but not to get folders the app doesn't have permissions in.
If we add the Music Library, Pictures Library and Videos Library to the Capabilities of the appxmanifest that we can use the GetParentAsync method to get the parent folder as a StorageFolder in these folder.
If you create a file or folder in the Downloads folder, we recommend that you add that item to your app's FutureAccessList so that your app can readily access that item in the future.
For more info, please refer the Locations Windows Store apps can access.
So if you want to get the other folders and files in DownloadsFolder, you should be able to Open files and folders with a picker.
It looks like this isn't possible - You can try to get the storage folder by using the Path with System.IO directly like so
var downloadPath = System.IO.Path.GetDirectoryName(storageFile.Path);
var downloadsFolder = await StorageFolder.GetFolderFromPathAsync(downloadPath);
But GetFolderFromPathAsync seems to throw an exception, I think windows just won't give you a reference to this folder.
A solution is to use a folder picker ONCE to pick the downloads folder (as part of the inital setup of the app). After that the app has full access to the downloads folder.
This code needs to be called once:
var folderPicker = new FolderPicker();
folderPicker.SuggestedStartLocation = PickerLocationId.Downloads;
folderPicker.FileTypeFilter.Add("*");
StorageFolder folder = await folderPicker.PickSingleFolderAsync();
if (folder != null)
{
// Application now has read/write access to all contents in the picked folder
// (including other sub-folder contents)
Windows.Storage.AccessCache.StorageApplicationPermissions.
FutureAccessList.AddOrReplace("DownloadFolderToken", folder);
var messageDialog = new MessageDialog("Download folder: " + folder.Name);
await messageDialog.ShowAsync();
}
else
{
var messageDialog = new MessageDialog("Operation cancelled");
await messageDialog.ShowAsync();
}
This code can then be used to directly access the downloads folder:
var downloadsFolder = await StorageApplicationPermissions.FutureAccessList.GetFolderAsync("DownloadFolderToken");
IReadOnlyList <StorageFile> fileList = await downloadsFolder.GetFilesAsync();
StringBuilder outputText = new StringBuilder();
outputText.AppendLine("Files:");
foreach (StorageFile file in fileList)
{
outputText.Append(file.Name + "\n");
await file.DeleteAsync();
}

Save FolderPicker location for next time in windows 10 universal apps c#

I am getting file by using FolderPicker from device, by using this below code.
FolderPicker pk = new FolderPicker();
pk.SuggestedStartLocation = PickerLocationId.Downloads;
pk.ViewMode = PickerViewMode.Thumbnail;
pk.FileTypeFilter.Add("*");
var folder = await pk.PickSingleFolderAsync();
var files =await folder.GetFilesAsync();
foreach (var files in files)
{
}
For each time i have to pick the folder location, for that reason i want to save the folder location first time, when i open app next time get the file from that path, any one please help me to achieve this.
Thank you,
Use the FolderPicker.SettingsIdentifier for that. If you set the value to something like "My Downloads" then the next time you use the picker, it will start in the location you picked previously.
I found the answer in MSDN forms https://social.msdn.microsoft.com/Forums/windowsapps/en-US/b5a23a11-f526-4a59-bcca-af6a563589d9/save-folderpicker-location-for-next-time-in-windows-10-universal-apps-c?forum=wpdevelop

c# UWP Save StorageFile Without Dialog

I am in trouble with some issue about FileSavePicker. Is there any solution about saving a StorageFile without showing any popup or dialog to ask user. I want to give the current path of the storage file from code behind.
var byteArray = Convert.FromBase64String(Base64);
StorageFile file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync("file.jpg", CreationCollisionOption.ReplaceExisting);
await Windows.Storage.FileIO.WriteBytesAsync(file, byteArray);
var savePicker = new FileSavePicker();
savePicker.FileTypeChoices.Add("JPEG-Image", new List<string>() { ".jpg" });
savePicker.SuggestedSaveFile = file;
savePicker.PickSaveFileAsync();
...We have to use a few paths which are defined under
'Windows.Storage.KnownFolders'...
it is not so. In fact your app can access any folder on device but it will need additional permissions. The most straightforward way to obtain permission you should do next:
1) ask user to pick folder from FolderPicker
2) store selected folder to StorageApplicationPermissions.FutureAccessList
After this your app can do anything with this folder.
Code that demonstrate how to obtain permissions:
var picker = new FolderPicker();
var pfolder = await picker.PickSingleFolderAsync();
StorageApplicationPermissions.FutureAccessList.Add(pfolder);
Code that demonstrate how to create file in desired folder:
var folder = await StorageFolder.GetFolderFromPathAsync("your path");
var file = await folder.CreateFileAsync("text.txt");
using (var writer = await file.OpenStreamForWriteAsync())
{
await writer.WriteAsync(new byte[100], 0, 0);
}
But keep in mind that "your path" is folder or any of subfolder that was stored to StorageApplicationPermissions.FutureAccessList. More details here FutureAccessList
StorageFile.GetFileFromPathAsync() is probably what you are looking for. I think the file must be created beforehand for this method to work. Be aware that creating the file in some locations might need additional permissions or is even impossible (I don't know how UWP and UAC interact).
Another possibility is to use Win32 APIs inside UWP apps. Maybe this can solve your problem if the desired API is available.
I want to thank you all for your interest. I figured out the solution. If you do not want to use any dialog or prompting you can not use FileSavePicker. Here are the simple codes you need to converting Base64 string to image and save.
var byteArray = Convert.FromBase64String(Base64);
StorageFile file = await Windows.Storage.KnownFolders.SavedPictures.CreateFileAsync(
"file.jpg", CreationCollisionOption.ReplaceExisting);
await Windows.Storage.FileIO.WriteBytesAsync(file, byteArray);
I guess there is no way to give specific path. We have to use a few paths which are defined under Windows.Storage.KnownFolders. If it is not, please give some information about it.

Getting all files in UWP app folder

For UWP, it is easy to get all files in the app local folder as:
IReadOnlyList<StorageFile> files = await ApplicationData.Current.LocalFolder.GetFilesAsync();
You can now iterate on the files list and even get further info on individual files.
I would like a similar all-file-getter for an app folder, for instance, consider the /Assets folder where app *.png files are stored.
Single file with a known name is no problem; I can refer to it quite easily as:
StorageFile.GetFileFromApplicationUriAsync(new Uri(#"ms-appx:///Assets/StoreLogo.png"))
My question is, therefore, is there a similar thing for getting all files in an app folder, such as /Assets folder? Logically, it should be something like StorageFile.GetFilesFromApplicationFolderUriAsync(new Uri(#"ms-appx:///Assets")) but unaware if an equivalent of the LocalFolder shown above exists.
You can access you installation folder by using Package.InstalledLocation. Therefore your code can look like this:
StorageFolder appInstalledFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
StorageFolder assets = await appInstalledFolder.GetFolderAsync("Assets");
var files = await assets.GetFilesAsync();
var storageFolder = await ApplicationData.Current.LocalFolder.GetFolderAsync("Assets");
var files = await storageFolder.GetFilesAsync();
https://learn.microsoft.com/en-us/uwp/api/windows.storage.applicationdata

Categories