如何使用路径名从Windows Phone(8.1)音乐库中检索文件?

8
我正在让我的用户从音乐库中选择文件,并将所选文件的路径存储在本地。现在我的问题是如何从这些路径编程方式访问文件?以下是我尝试过的几件事情。
假设我的路径名为 D:\Xyz\abc.mp3
方法1:
StorageFolder S = KnownFolders.MusicLibrary;
StorageFile MyFile = await S.GetFileAsync("abc.mp3"); //文件未找到错误
//我认为这不起作用,因为 GetFileAsync 方法只能从当前文件夹获取文件
方法2:
S = await S.GetFolderAsync("Xyz"); //然后我计划执行GetFileAsync。但这也会导致文件夹未找到错误。
最后,我尝试了 S = await S.GetFolderAsync("D");
任何有关如何访问文件甚至实现目标的替代方法都非常棒!
注意:StorageFile.GetFileFromPathAsync("D:\Xyz\abc.mp3") 显示我没有权限访问。

GetFileFromPathAsync不能保证在Windows Phone 8.1上从选择器中访问文件。访问被拒绝是预期的结果。要保持访问,您将需要使用Windows.Storage.AccessCache命名空间。请参阅我的答案以了解一种保持对文件访问的方法。 - Adam
3个回答

10
如果您在 package.appxmanifest 文件中声明了以下内容:
  • Capabilities 中声明了 Music Library 权限
  • Declarations 中声明了 File Type Association (如果您仅访问 Music Library,则我不确定是否需要此项)
那么您就可以像这样从 Music Library 文件夹中检索文件:
StorageFolder folder = KnownFolders.MusicLibrary;
// below code will work unless 'fileName.mp3' is in 
// your Music folder either on phone or SD card
StorageFile file = await folder.GetFileAsync("fileName.mp3");
// you can access them also with path, but in this case
// also Folders must be in Music folder
string path = @"Test\ccc.mp3";
StorageFile file = await folder.GetFileAsync(path);

总结一下,您只能通过KnownFolders.MusicLibrary访问位于手机或SD卡上的音乐文件夹中的文件,其路径如下:

C:\Data\Users\Public\Music\test.mp3 - 适用于手机

D:\Music\Test\test2.mp3 - 适用于SD卡

请记住,通过StorageFolder.GetFileAsync()访问是相对于StorageFolder的(它也可以使用完整路径,详见下面的说明):

要检索的文件的名称(或相对于当前文件夹的路径)。

在这种情况下,要获取上述文件,您将使用像test.mp3Test\test2.mp3这样的文件名。

您将无法获取其他文件,例如D:\xxx.mp3 - 它不在音乐库中 - 它在SD卡上,如果您想要访问它,您必须通过KnownFolders.RemovableDevices进行操作 - 当您添加所需的功能后,您应该能够通过完整路径进行访问。但是,请也记住下面的说明:

不要依赖此属性来访问文件,因为某些文件可能没有文件系统路径。例如,如果文件由URI支持或使用文件选择器选择,则不能保证该文件具有文件系统路径。

在我们的讨论中,您正在使用CommonFileQuery.OrderByName获取文件。根据我检查,在那里可能存在一个小错误 - 在VS描述中说:

深度查询的查询结果包括要查询的文件夹中所有子文件夹中的所有文件,并根据指定的元数据对它们进行排序。

运行以下代码:

// a method to retrieve files from Musiic Library recursively 
private async Task RetriveFilesInFolders(List<StorageFile> list, StorageFolder parent)
{
   foreach (var item in await parent.GetFilesAsync()) list.Add(item);
   foreach (var item in await parent.GetFoldersAsync()) await RetriveFilesInFolders(list, item);
}

// then I've used it like this:

StorageFolder folder = KnownFolders.MusicLibrary;

List<StorageFile> listOfFiles = new List<StorageFile>();
await RetriveFilesInFolders(listOfFiles, folder);
// as a result of above code I have a List of 5 files that are in Music Library

List<IStorageItem> filesFolders = (await folder.GetItemsAsync()).ToList();
List<StorageFile> items = (await folder.GetFilesAsync(CommonFileQuery.OrderByName)).ToList();
// as a result here I've 14 files that are in Music Library and SD card, and Phone

已经给出了结果:

  • 在第一种情况下,有5个文件实际上位于音乐文件夹及其子文件夹中,
  • 在第二种情况下-有14个文件分别位于:音乐库、SD卡和手机中

您可以在调试模式下轻松查看路径,您会发现第二种方法中的某些文件具有D:\file.mp3等等 - 它们不在音乐库中 - 因此您将无法通过KnownFolders.MusicLibrary获取它们。 如果您想获得它们,则必须使用其他已知文件夹 - 在这种情况下是SD卡:

StorageFolder externalDevices = Windows.Storage.KnownFolders.RemovableDevices;
StorageFolder sdCard = (await externalDevices.GetFoldersAsync()).FirstOrDefault();
StorageFile file = await sdCard.GetFileAsync("xyz.mp3"); // for D:\xyz.mp3
StorageFile file = await sdCard.GetFileAsync("XYZ\xyz.mp3"); // for D:\XYZ\xyz.mp3

在我的情况下,我不得不添加“可移动存储”功能(除了音乐库)。之后,它开始工作。 - Illidan
@Romasz,我想要的只是访问KnownFolders.MusicLibrary文件夹。在我声明“可移动存储”之前,我一直被拒绝访问。在我声明之后,它开始工作了。 - Illidan
@Romasz:我想知道当用户更改他的音乐库内容时,您是如何更新列表的。您是否每次应用程序打开时都通过使数据持久化来进行检查,因为这需要很长时间,还是尝试在后台进行? - AbsoluteSith
@AbsoluteSith 目前我没有这样的需求。没有可用的事件可以帮助你。我认为最好的方法是为用户提供一个按钮,比如“同步”,或者在后台以某种指示器运行来完成,通知用户正在进行某些操作。 - Romasz
@Romasz:感谢你的帮助,我会去看看的。 - AbsoluteSith
显示剩余10条评论

2
首先,请确保您已设置了正确的功能。您收到的错误是如果您没有声明正确的CAP_ID时会看到的错误。下面是一张截图: enter image description here 关于文件路径,取决于文件存储的位置,您可能需要使用双斜杠。我曾遇到类似的问题,我通过以下方法解决:
"isostore:shared\\folderName\\NameOfFile.mp3"
您可以在我的SO帖子中查看整个过程。

这是一个WP 8.1应用程序,我已经勾选了音乐库功能。我正在从库中获取所有文件并让用户选择它们。然后我存储文件路径,到目前为止都还好。现在我想在我的应用程序中稍后访问这些文件。是的,双斜杠,仍然一样。 - Aditya

1
你需要使用 访问缓存来存储文件的访问,而不是路径。这将允许您立即使用StorageFile对象进行处理,并有助于处理一些涉及文件移动的情况。
要将文件存储在访问缓存中,请执行以下操作:
 StorageFile file; //Get a file
 string mruToken = Windows.Storage.AccessCache.StorageApplicationPermissions.MostRecentlyUsedList.Add(file, "20120716");

你需要把token保存在某个地方。从缓存中获取文件的方法如下:
 StorageFile file = await Windows.Storage.AccessCache.StorageApplicationPermissions.MostRecentlyUsedList.getFileAsync(mruToken);

仅存储路径可能会导致驱动器字母发生变化等问题。这样做可以确保如果文件仍然可用,您的应用程序可以获取它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接