15

I've two files with the same name in KnownFolders.VideosLibrary, in this case I cannot access file by its Name hence it will return only the first one. Therefore is there any other way to get the file other that parsing all files in folder?

// this return two files 
var files = (await KnownFolders.VideosLibrary.GetFilesAsync()).Where(x => x.Name == "test.txt").ToArray();
// with this I can get only one file
StorageFile file = await KnownFolders.VideosLibrary.GetFileAsync("test.txt");
// of course I can parse it with query, but I would like to avoid it
// StorageFile myFile = (await KnownFolders.VideosLibrary.GetFilesAsync()).FirstOrDefault(x => x.FolderRelativeId == "something");

I'm aware of FutureAccessList, but it can hold only up to 1000 files, what is not enough for me.


Some clarification after request:

For example lets consider that app run on phone with SD card. I've one file in Videos in phone's memory with name test.txt, the file with the same name exists also on SD card in Videos folder.

In this situation when you call the first line in code above, you will get two files, to differentiate them system provides FolderRelativeId, so files with the same name can exist in one 'location'. If you take a look at the full path of each folder one will likely have C:\Viedos\test.txt and the second D:\Videos\test.txt.

Now user on the first run picked a file with FilePicker and I've remembered its path for example D:\Videos\test.txt. On the second run of the app I would like to have access to this file by using its path (or other method apart from limited FutureAccessList). In the past I used to do it by StorageFile.GetFileFromPathAsync(path); - by it seems that it starts throwing UnauthorizedAccessException in W10.

Community
  • 1
  • 1
Romasz
  • 29,662
  • 13
  • 79
  • 154
  • why just don't use loop for each file in files? what is type of files (your variable)? The second thing is I wonder how it's possible to have 2 files with the same name – Tomasz Pikć Dec 06 '15 at 15:05
  • @TomaszPikć It's a performance drawback if have to use a look when I know file's path, imagine when I have a directory with 1000 files and I 've to perform few file operations. As for the second thing - libraries are virtual locations and it's quite easy to have to same files - you can for example in Videos on phone's memory and on sd card have files with the same name, then in VideosLibrary they will have same name, but different relativefolderid. – Romasz Dec 06 '15 at 20:05
  • "Therefore is there any other way to get the file other that parsing all files in folder?" - You already answered your question. `StorageFilder.GetFileAsync` will return the file you're searching for. If this isn't what you're looking for, please specify your question more. – Stefan Over Dec 07 '15 at 08:10
  • @Herdo I've edited the question to add more clarification. Tell me if you need more. – Romasz Dec 07 '15 at 08:40
  • Your code will return all files that have the given name. I don't see how you can do anything other than iterate over them, unless you know other info about the file, like the path, create date, size, or whatever. – Tony Vitabile Dec 08 '15 at 14:13
  • @TonyVitabile I know the exact path of the file, for example `C:\Videos\test.txt`, though lets say that I cannot assume that it belongs to *VideosLibrary*. Simply, now *GetFileFromPathAsync()* throws exception - so I'm looking for other methods. Moreover - I can know everything of the file as it has been picked for the first time. Now on second run of the app I would like to access that file without prompting the user again. – Romasz Dec 08 '15 at 14:18

4 Answers4

2

You can get the instance of IStorageFile by this.

// If your have a StorageFile objece file then 
//fileUri = new Uri(file.Path);

string uri = fileUri.LocalPath;
int end = uri.LastIndexOf('\\');
uri = uri.Substring(0, end + 1);

string name = Path.GetFileName(fileUri.LocalPath);
var folder = await StorageFolder.GetFolderFromPathAsync(uri);
IStorageFile file = await folder.GetFileAsync(name);
// Do something with file object
Aman Sharma
  • 698
  • 7
  • 17
0

According to this documentation from MS, that apps can opt out of allowing files to be stored on the SD card. As a result, the media libraries can be split across the device's internal storage and the SD card.

If I get this right, your solution would be:

  • Opt out the feature mentioned above
  • You should now only search on the local device, not the SD card
    • This will result in unique file names in each directory
  • If your use-case requires to search for the file on SD cards as well, you now have to access the SD card, and query the file here

I'm not sure, if the coding overhead of accessing the SD card separately, if worth the performance gain by only querying the local storage.

Stefan Over
  • 5,851
  • 2
  • 35
  • 61
  • I cannot opt out splitting the library as it doesn't depend on me - the user decides where he will store files. Also, as I've understood you opt for searching a file, and I would like to avoid this as I already know where file exists via it's path. The problem is that *StorageFile.GetFileFromPathAsync(path)* doesn't seem to work anymore. – Romasz Dec 07 '15 at 11:19
0

When you open a file with a file picker in a Windows 8.1 app (I'm assuming Windows 10 works the same way) you are obtaining a rights token to that folder that lasts for a period of time, or until you quit the application. When you reopen the application, you have to re-obtain a token to the folder.

Read this article about the StorageApplicationPermissions object.

The Sharp Ninja
  • 1,041
  • 9
  • 18
  • The problem is how to re-obtain that token. In W/WP8.1 it was possible to do it via StorageFile.GetFileFromPath, in W10 it throws exception. Therefore I'm looking for other possibilities. – Romasz Dec 15 '15 at 06:20
  • what's the exception that it throws? – The Sharp Ninja Dec 15 '15 at 06:32
  • You're right @Romasz, that behavior has changed in Windows 10, even from an 8.1 app. I guess we'll have to dig deeper. – The Sharp Ninja Dec 15 '15 at 06:34
  • What you can do is remember the file before quitting the app. You get a string token for it using StorageApplicationPermissions.MostRecentlyUsedList.Add( storageFile). Later on you can get the file back using StorageApplicationPermissions.MostRecentlyUsedList.GetFileAsync( stringToken). Put the token into LocalSettings. Note there is a limit on how many you can keep in MostRecentlyUsedList, so if you are doing this over and over you will have to Clear() the list. – sjb-sjb Dec 20 '17 at 12:25
0

I guess one could rationalize the UnauthorizedAccessException thrown when calling StorageFile.GetFileFromPathAsync(path) by considering that you don't have access to a root drive letter from your app, so navigating the folder structure that way is not allowed. It's a guess though.

As for your problem, why aren't you able to do this?

var file = (await KnownFolders.VideosLibrary.GetFilesAsync()).FirstOrDefault(x => x.Path == "D:\Videos\test.txt");

Where D:\Videos\test.txt is the .Path property value that you grabbed from the file that the user selected using the picker.

Perhaps you can expect it to be a little slower when there are millions of files on the VideosLibrary.

Mike
  • 2,220
  • 1
  • 18
  • 32
  • Seems like you are proposing the same method like the one I've commented out in my code in question. I would like to avoid parsing the folder. As a side note, it was possible in 8.1 but seems like in UWP it has changed cause of security reasons. – Romasz Jun 10 '16 at 21:06