How to access user files? - c#

I am developing a Windows 10 UWP application and anytime I run the below code, I get the following execption:
'UnauthorizedAccessException - Access to path {path name} is denied'.
I have tried the several windows folders (path) :
Pictures,
Videos
Desktop etc.
This is my code:
public async Task GetFiles() // edit added wrapper method for readability
{
var filePicker = new FileOpenPicker();
filePicker.FileTypeFilter.Add("*");
Windows.Storage.StorageFile file = await filePicker.PickSingleFileAsync();
if (file != null)
{
ChosenFiles.ItemsSource = GetFileInfo(file.Path);
}
}
public List<string> GetFileInfo(string path)
{
List<string> files = new List<string>();
string[] allFiles = Directory.GetFiles(path);
foreach (var file in allFiles)
{
FileInfo Info = new FileInfo(file);
files.Add(Info.Name);
}
return files;
}

System.IO.Directory seems to only have direct access to app package and app local storage folders. That means you should rather use StorageFile and StorageFolder classes to extract information you need. For example:
private async void ButtonBase_OnClick(object sender, RoutedEventArgs args)
{
var folderPicker = new FolderPicker();
var folder = await folderPicker.PickSingleFolderAsync();
if (folder != null)
{
ChosenFiles.ItemsSource = await GetFileInfoAsync(folder);
}
}
public async Task<List<string>> GetFileInfoAsync(StorageFolder folder)
{
List<string> files = new List<string>();
var allFiles = await folder.GetFilesAsync();
foreach (var file in allFiles)
{
files.Add(file.Name);
}
return files;
}
Note that if you picked a file, you can't enumerate its neighbors because you don't have access to its parent folder. So for your scenario you should use FolderPicker.

Related

CopyAsync in parallel?

I'm currently copying some files from my Assets into my LocalStorage folder.
What I'm doing is working but I was wondering if there was a way to make that part run in parallel :
foreach (StorageFile f in files)
{
await f.CopyAsync(postes);
}
I tried something like that but of course it's not working because CopyAsync is not returning a Task and can not be cast to a Task :
var tasks = new List<Task>();
foreach (StorageFile f in files)
{
var task = (Task)f.CopyAsync(postes);
tasks.Add(task);
}
await Task.WhenAll();
Complete code :
public async Task loadDefaultPosteInformationAsync()
{
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
StorageFolder postes = await localFolder.CreateFolderAsync("Postes");
StorageFolder appInstalledFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
StorageFolder assets = await appInstalledFolder.GetFolderAsync(#"Assets\Postes");
var files = await assets.GetFilesAsync();
foreach (StorageFile f in files)
{
await f.CopyAsync(postes);
}
}

How to create a subfolder in a subsubfolder SharePoint Online C#

I want to create some folders in the document library in C#.
The folder structure should be as follows in the document library:
"98_Projekte" --> "Muster Mandant" --> "01 Test Subfolder"
In my C# code, I only create the sub folder "Muster Mandant" in "98_Projekte". That is correct, but I want afterwards to create new subfolders in "Muster Mandant" (see second foreach).
public static void AddFolder(ClientContext context, string[] folders)
{
Web web = context.Web;
var docLibrary = web.DefaultDocumentLibrary().RootFolder;
context.Load(docLibrary);
context.ExecuteQuery();
foreach (Microsoft.SharePoint.Client.Folder subFolder in docLibrary.Folders)
{
if (subFolder.Name == "98_Projekte")
{
subFolder.Folders.Add("Muster Mandant");
context.ExecuteQuery();
docLibrary = subFolder;
docLibrary.Update();
}
}
foreach (Microsoft.SharePoint.Client.Folder subSubFolder in docLibrary.Folders)
{
if (subSubFolder.Name == "Muster Mandant")
{
foreach (string folder in folders)
{
subSubFolder.Folders.Add(folder);
}
}
}
context.ExecuteQuery();
}
}
Do you have any solutions?
You may check below code.
public static Folder AddSubFolder(ClientContext context, Folder ParentFolder, string folderName)
{
Folder resultFolder=ParentFolder.Folders.Add(folderName);
context.ExecuteQuery();
return resultFolder;
}
static void Main(string[] args)
{
using (var context = new ClientContext("https://domain.sharepoint.com/sites/TST/"))
{
string password = "pw";
SecureString sec_pass = new SecureString();
Array.ForEach(password.ToArray(), sec_pass.AppendChar);
sec_pass.MakeReadOnly();
context.Credentials = new SharePointOnlineCredentials("lee#domain.onmicrosoft.com", sec_pass);
Web web = context.Web;
var folders = web.DefaultDocumentLibrary().RootFolder.Folders;
context.Load(folders);
context.ExecuteQuery();
foreach (Folder subFolder in folders)
{
if (subFolder.Name == "98_Projekte")
{
Folder parent1= AddSubFolder(context,subFolder,"Muster Mandant");
AddSubFolder(context, parent1, "01 Test Subfolder");
}
}
Console.WriteLine("Done");
Console.ReadKey();
}
}
I think the problem is that your code is expecting the .Folders property to contain all folders (recursive) and instead you are just getting the direct children of the root folder. In your 2nd loop check the context of the docLibrary.Folders property/collection and see what is returned.

UWP cannot get access to folder from hard drive via FolderPicker

I want to read all images files from some folder in the local hard drive (including sub folders) with a UWP app.
im starting with FolderPicker so the user can pick the wanted folder:
public async static Task<string> GetFolderPathFromTheUser()
{
FolderPicker folderPicker = new FolderPicker();
folderPicker.ViewMode = PickerViewMode.Thumbnail;
folderPicker.FileTypeFilter.Add(".");
var folder = await folderPicker.PickSingleFolderAsync();
return folder.Path;
}
after successfully getting the folder path i'm trying to access the folder:
public async static Task<bool> IsContainImageFiles(string path)
{
StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(path);
IReadOnlyList<StorageFile> temp= await folder.GetFilesAsync();
foreach (StorageFile sf in temp)
{
if (sf.ContentType == "jpg")
return true;
}
return false;
}
and then I'm getting the next exception :
An exception of type 'System.UnauthorizedAccessException' occurred in mscorlib.ni.dll but was not handled in user code
WinRT information: Cannot access the specified file or folder (D:\test). The item is not in a location that the application has access to (including application data folders, folders that are accessible via capabilities, and persisted items in the StorageApplicationPermissions lists). Verify that the file is not marked with system or hidden file attributes.
So how can I get access to read the files from the folder?
Thanks.
Once you get a folder from the file picker, you may not be able to access the folder through its path. You need to directly use the StorageFolder instance returned:
public async static Task<IStorageFolder> GetFolderPathFromTheUser()
{
FolderPicker folderPicker = new FolderPicker();
folderPicker.ViewMode = PickerViewMode.Thumbnail;
folderPicker.FileTypeFilter.Add(".");
var folder = await folderPicker.PickSingleFolderAsync();
return folder;
}
public async static Task<bool> IsContainImageFiles(IStorageFolder folder)
{
IReadOnlyList<StorageFile> temp= await folder.GetFilesAsync();
foreach (StorageFile sf in temp)
{
if (sf.ContentType == "jpg")
return true;
}
return false;
}
If you want to access it later, you should add it to future access list and keep the returned token:
public async static Task<string> GetFolderPathFromTheUser()
{
FolderPicker folderPicker = new FolderPicker();
folderPicker.ViewMode = PickerViewMode.Thumbnail;
folderPicker.FileTypeFilter.Add(".");
var folder = await folderPicker.PickSingleFolderAsync();
return FutureAccessList.Add(folder);
}
public async static Task<bool> IsContainImageFiles(string accessToken)
{
IStorageFolder folder = await FutureAccessList.GetFolderAsync(accessToken);
IReadOnlyList<StorageFile> temp= await folder.GetFilesAsync();
foreach (StorageFile sf in temp)
{
if (sf.ContentType == "jpg")
return true;
}
return false;
}

OneDrive Upload/Download to Specified Directory

I'm trying to use the Live SDK (v5.6) to include backup/restore from OneDrive in my Windows Phone 8.1 Silverlight application. I can read/write to the standard "me/skydrive" directory, but I am having a horrible time in finding a way to upload/download to a specified directory. I can create the folder if it doesn't exist no problem.
I have been trying below with no luck.
var res = await _client.UploadAsync("me/skydrive/mydir", fileName, isoStoreFileStream, OverwriteOption.Overwrite);
I've also tried getting the directory ID and passing that in also.
var res = await _client.UploadAsync("me/skydrive/" + folderId, fileName, isoStoreFileStream, OverwriteOption.Overwrite);
Same error.. I receive 'mydir' or the id isn't supported...
"{request_url_invalid: Microsoft.Live.LiveConnectException: The URL contains the path 'mydir', which isn't supported."
Any suggestions? If you suggest an answer for the uploadasync, could you also include how I could download my file from the specified directory? Thanks!
Here's an extension method that checks if a folder is created and:
If created returns the folder id.
If not created, creates it and returns the folder id.
You can then use this id to upload to and download from that folder.
public async static Task<string> CreateDirectoryAsync(this LiveConnectClient client,
string folderName, string parentFolder)
{
string folderId = null;
// Retrieves all the directories.
var queryFolder = parentFolder + "/files?filter=folders,albums";
var opResult = await client.GetAsync(queryFolder);
dynamic result = opResult.Result;
foreach (dynamic folder in result.data)
{
// Checks if current folder has the passed name.
if (folder.name.ToLowerInvariant() == folderName.ToLowerInvariant())
{
folderId = folder.id;
break;
}
}
if (folderId == null)
{
// Directory hasn't been found, so creates it using the PostAsync method.
var folderData = new Dictionary<string, object>();
folderData.Add("name", folderName);
opResult = await client.PostAsync(parentFolder, folderData);
result = opResult.Result;
// Retrieves the id of the created folder.
folderId = result.id;
}
return folderId;
}
You then use this as:
string skyDriveFolder = await CreateDirectoryAsync(liveConnectClient, "<YourFolderNameHere>", "me/skydrive");
Now skyDriveFolder has the folder id that you can use when uploading and downloading. Here's a sample Upload:
LiveOperationResult result = await liveConnectClient.UploadAsync(skyDriveFolder, fileName,
fileStream, OverwriteOption.Overwrite);
ADDITION TO COMPLETE THE ANSWER BY YnotDraw
Using what you provided, here's how to download a text file by specifying the file name. Below does not include if the file is not found and other potential exceptions, but here is what works when the stars align properly:
public async static Task<string> DownloadFileAsync(this LiveConnectClient client, string directory, string fileName)
{
string skyDriveFolder = await OneDriveHelper.CreateOrGetDirectoryAsync(client, directory, "me/skydrive");
var result = await client.DownloadAsync(skyDriveFolder);
var operation = await client.GetAsync(skyDriveFolder + "/files");
var items = operation.Result["data"] as List<object>;
string id = string.Empty;
// Search for the file - add handling here if File Not Found
foreach (object item in items)
{
IDictionary<string, object> file = item as IDictionary<string, object>;
if (file["name"].ToString() == fileName)
{
id = file["id"].ToString();
break;
}
}
var downloadResult= await client.DownloadAsync(string.Format("{0}/content", id));
var reader = new StreamReader(downloadResult.Stream);
string text = await reader.ReadToEndAsync();
return text;
}
And in usage:
var result = await DownloadFile(_client, "MyDir", "backup.txt");

how to empty a directory in c# xaml metro style?

i have this c# code and i want to delete a certain sub directory in Documents Library. However this produces an error because the directory is not empty. I hope someone can guide me on how to do this.
thank you for any prompt reply.
StorageFolder storageFolder = KnownFolders.DocumentsLibrary;
var queryResult = storageFolder.CreateFolderQuery();
IReadOnlyList<StorageFolder> folderList = await queryResult.GetFoldersAsync();
foreach (StorageFolder folder in folderList)
{
await folder.DeleteAsync();
}
You could use the StorageFolder.GetFilesAsync() to obtain a list of all the files present in the folders and delete them prior to deleting the folders since there is no way in the DeleteAsync() method to specify subfolders and files.
More info: StorageFolder class | MSDN
Hope this may help.
public async void deletefile()
{
StorageFolder sourceFolder = ApplicationData.Current.TemporaryFolder;
// sourceFolder = await sourceFolder.GetFolderAsync("Test");
// await sourceFolder.DeleteAsync(StorageDeleteOption.PermanentDelete);
// var files = await sourceFolder.GetFilesAsync();
IReadOnlyList<StorageFile> folderList = await sourceFolder.GetFilesAsync();
if (folderList.Count > 0)
{
foreach (StorageFile f1 in folderList)
{
await f1.DeleteAsync(StorageDeleteOption.PermanentDelete);
}
}
//StorageFile retfile = await ApplicationData.Current.TemporaryFolder.GetFileAsync("MysoundFile.mp3");
// if (retfile != null)
// {
// await retfile.DeleteAsync(StorageDeleteOption.PermanentDelete);
// }
}

Categories