Is there any other way of checking whether a file exists in a Windows Store app?
try
{
var file = await ApplicationData.Current.LocalFolder.GetFileAsync("Test.xml");
//no exception means file exists
}
catch (FileNotFoundException ex)
{
//find out through exception
}
According to the accepted answer in this post, there is no other way at the moment. However, the File IO team is considering changing the the api so that it returns null instead of throwing an exception.
Quote from the linked post:
Currently the only way to check if a file exists is to catch the
FileNotFoundException. As has been pointed out having an explicit
check and the opening is a race condition and as such I don't expect
there to be any file exists API's added. I believe the File IO team
(I'm not on that team so I don't know for sure but this is what I've
heard) is considering having this API return null instead of throwing
if the file doesn't exist.
This may be old, but it looks like they've changed how they want you to approach this.
You're supposed to attempt to make the file, then back down if the file already exists. Here is the documentation on it. I'm updating this because this was the first result on my Google search for this problem.
So, in my case I want to open a file, or create it if it doesn't exist. What I do is create a file, and open it if it already exists. Like so:
save = await dir.CreateFileAsync(myFile, CreationCollisionOption.OpenIfExists);
I stumbled on to this blog post by Shashank Yerramilli which provides a much better answer.
I have tested this for windows phone 8 and it works. Haven't tested it on windows store though
I am copying the answer here
For windows RT app:
public async Task<bool> isFilePresent(string fileName)
{
var item = await ApplicationData.Current.LocalFolder.TryGetItemAsync(fileName);
return item != null;
}
For Windows Phone 8
public bool IsFilePresent(string fileName)
{
return System.IO.File.Exists(string.Format(#"{0}\{1}", ApplicationData.Current.LocalFolder.Path, fileName);
}
Check if a file exists in Windows Phone 8 and WinRT without exception
You can use the old Win32 call like this to test if directory exist or not:
GetFileAttributesExW(path, GetFileExInfoStandard, &info);
return (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? false: true;
It works in Desktop and Metro apps:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa364946%28v=vs.85%29.aspx
Microsoft has added a new function to StorageFile in Windows 8.1 to allow user engineers to determine if a file can be accessed: IsAvailable
The other means to check is by getting files in local folder
var collection = ApplicationData.Current.LocalFolder.GetFilesAsync()
Using this method and then iterating over all the elements in the collection and check for its availability.
I tried to write my own using old tricks:
GetFileAttributesEx() always seems to end up with ERROR_ACCESS_DENIED if file selected via FileOpenPicker;
Ditto for FindFirstFileEx();
_stat() always ends up with ENOENT when file selected via FileOpenPicker;
CreateFile2() with CREATE_NEW option works -- if file does exist it will fail with INVALID_HANDLE_VALUE return value and ERROR_FILE_EXISTS last error; if file does not exist you have to remember to delete created file afterwards.
All in all -- you're better of sticking with exception handling method.
8.1 got something like this, I tried it worked.
var folder = ApplicationData.Current.LocalFolder;
var file = await folder.TryGetItemAsync("mytext.txt") as IStorageFile;
if (file == null)
{
//do what you want
}
else
{
//do what you want
}
http://marcominerva.wordpress.com/2013/11/19/how-to-check-if-a-file-exists-in-a-windows-8-1-store-apps-no-more-exception-handling/
Dim myPath As StorageFolder
If (From i In Await KnownFolders.MusicLibrary.GetFoldersAsync() Where i.Name = "PodBong").Count = 1 Then
myPath = Await KnownFolders.MusicLibrary.GetFolderAsync("PodBong")
Else
myPath = Await KnownFolders.MusicLibrary.CreateFolderAsync("PodBong")
End If
The documentation for TryGetItemAsync says, "This example shows how to checkfor the existence of a file." It seems that this API is officially intended to serve that purpose.
Related
Every time I save a file and delete it right away using the function below, I keep getting this error message: "System.IO.IOException: The process cannot access the file because it is being used by another process".
Waiting for a couple of minutes or closing visual studio seems to only unlock the files that you uploaded previously.
public static bool DeleteFiles(List<String> paths)
{ // Returns true on success
try
{
foreach (var path in paths)
{
if (File.Exists(HostingEnvironment.MapPath("~") + path))
File.Delete(HostingEnvironment.MapPath("~") + path);
}
}
catch (Exception ex)
{
return false;
}
return true;
}
I think that the way I'm saving the files may cause them to be locked. This is the code for saving the file:
if (FileUploadCtrl.HasFile)
{
filePath = Server.MapPath("~") + "/Files/" + FileUploadCtrl.FileName;
FileUploadCtrl.SaveAs(filePath)
}
When looking for an answer I've seen someone say that you need to close the streamReader but from what I understand the SaveAs method closes and disposes automatically so I really have no idea whats causing this
After some testing, I found the problem. turns out I forgot about a function I made that was called every time I saved a media file. the function returned the duration of the file and used NAudio.Wave.WaveFileReader and NAudio.Wave.Mp3FileReader methods which I forgot to close after I called them
I fixed these issues by putting those methods inside of a using statement
Here is the working function:
public static int GetMediaFileDuration(string filePath)
{
filePath = HostingEnvironment.MapPath("~") + filePath;
if (Path.GetExtension(filePath) == ".wav")
using (WaveFileReader reader = new WaveFileReader(filePath))
return Convert.ToInt32(reader.TotalTime.TotalSeconds);
else if(Path.GetExtension(filePath) == ".mp3")
using (Mp3FileReader reader = new Mp3FileReader(filePath))
return Convert.ToInt32(reader.TotalTime.TotalSeconds);
return 0;
}
The moral of the story is, to check if you are opening the file anywhere else in your project
I think that the problem is not about streamReader in here.
When you run the program, your program runs in a specific folder. Basically, That folder is locked by your program. In that case, when you close the program, it will be unlocked.
To fix the issue, I would suggest to write/delete/update to different folder.
Another solution could be to check file readOnly attribute and change this attribute which explained in here
Last solution could be using different users. What I mean is that, if you create a file with different user which not admin, you can delete with Admin user. However, I would definitely not go with this solution cuz it is too tricky to manage different users if you are not advance windows user.
I have a question regarding accessing data from another application.
I need access to files that are inside another, already installed, application on iPhone so they can be uploaded via REST POST method.
When we tried testing this with simple picker [FileData fileData = await CrossFilePicker.Current.PickFile();] and navigating to the other application we got something along the lines of 'access denied' message.
We've done this on Android while using Android.App.Application.Context(StartActivity and StartActivityForResault) and Intents (ActionGetContent).
I've read a few articles on Accessing data from another application but I did not fully understand the concept of 'application sandbox'.
Is it even possible? If so, can you give me an example or link to follow so I can see how it's done?
You can have a try with Xamarin.Essentials: Share to share data between apps.
Files:
var fn = "Attachment.txt";
var file = Path.Combine(FileSystem.CacheDirectory, fn);
File.WriteAllText(file, "Hello World");
await Share.RequestAsync(new ShareFileRequest
{
Title = Title,
File = new ShareFile(file)
});
Till now all cases I met was like:
try to store file
if file is stored that's fine
if file can not be stored tell about it (no path, no permission, etc)
Currently I am standing before problem how to check if file can be stored without storing it. In general I don't even know what to ask Google, because all returned results I got are about permissions, and general in Linux, and I need it under C#/Windows.
How such checking can be done?
Since you don't want to attempt writing to the folder, you could consider this approach.
You can put a try catch around this:
System.Security.AccessControl.DirectorySecurity ds = Directory.GetAccessControl(folderPath);
i.e.
public bool CanWriteToPath(string folderPath)
{
try
{
var ds = Directory.GetAccessControl(folderPath);
return true;
} catch (UnauthorizedAccessException)
{
return false;
}
}
It will only succeed if you have permissions.
Sorry that it still has to use a try/catch.
How about use try catch block? If any exception occurs - you can catch it and determine than can not save file. If no exception occurs, file successfully saved.
There is a Directory.GetAccessControl method and File.GetAccessControl method in File.IO namespace.
If you want to know the status before actually writing the file, check if the specified directory has write permissions for the user. If all is well, write the file. You could also use a try catch block as suggested in other answers.
I'm running the following code to delete a file that does exist:
try
{
var folder = ApplicationData.Current.LocalFolder;
var path = rendition.OfflineLocation.Replace(folder.Path, "");
var file = await folder.GetFileAsync(path);
await file.DeleteAsync();
}
catch (FileNotFoundException)
{
}
When this runs the file.DeleteAsync(); gives an ArgumentException, with the message Value does not fall within the expected range.
I can't find any information anywhere why I would be getting this. Any ideas?
Call Stack:
at Windows.Storage.StorageFile.DeleteAsync()
at Lightning.Services.DownloaderService.d__36.MoveNext() in e:\\Services\DownloaderService.cs:line 120
Line 120 is the DeleteAsync line.
I suspect there's something wrong with your path value. I've already written a blogpost on this subject because WinRT exceptions can be pretty inconsistent and misleading.
I'd suggest two things to help you get to the bottom of things:
Check the value of StorageFile.Path property and make sure there are no double \ in it and that it indeed points into ApplicationData.Current.LocalFolder folder.
Try calling FileIO.ReadBufferAsync with the same path. You might get a better exception.
Also, why not simply call StorageFile.GetFileFromPathAsync if you already have the full path instead of manipulation the string?
My guess is you're leaving a slash prepended to the path you are trying to delete - you're replacing the folder path, which iirc does not include the trailing slash.
First, here is my code:
private Shoe ProcessForm(Shoe shoe, HttpPostedFileBase image)
{
try
{
shoe.Slug = CMSHelper.SanitizeTitle(shoe.Name);
shoe.LastModification = DateTime.Now;
if ((image != null) && (image.ContentLength > 0))
{
string fileName = String.Concat(shoe.ShoeId, Path.GetExtension(image.FileName));
shoe.Image = fileName;
string filePath = Path.Combine(Server.MapPath(shoe.ImagePath), fileName);
image.SaveAs(filePath);
}
}
catch (Exception e)
{
throw e;
}
return shoe;
}
Locally, this code works fine. Directories' permissions are fine. And it has worked before randomly on other servers (I tested this code on 4 or 5 different servers while I was testing VPS providers).
But if I try to run it from my home computer, everything passes alright, there's a file name saved in the database but no file is uploaded. And no exceptions are given!!!
I've been trying to fix this for almost three days and so much useless hours, please help me... I just don't see what's wrong with this...
I finally did a workaround which is doing very fine. I even asked at my job and everyone said there was nothing wrong at all. So screw it here's what I did:
Instead of calling .SaveAs() I made a method which is :
public static void WriteFileFromStream(Stream stream, string toFile)
{
using (FileStream fileToSave = new FileStream(toFile, FileMode.Create))
{
stream.CopyTo(fileToSave);
}
}
I call it like this:
CMSHelper.WriteFileFromStream(image.InputStream, filePath);
And that's it.
What is your view model? First of all replace (Shoe shoe, HttpPostedFileBase image) with (FormCollection formCollection). Put a breakpoint on that to see that you are getting all the submitted values. If you do then there is a problem with model binding and we'll need to address that.
Edit
Can you please put a breakpoint on
image.SaveAs(filePath);
Add a watch for fileName and filePath variables. I think that server path is not what you expect it to be, or maybe you are looking in the wrong folder all together. Tell us what are the values of those variables. Also make sure that no exception is thrown when you go past image.SaveAs(filePath);
image.FileName contains the path data and is selected by
Path.Combine(Server.MapPath(shoe.ImagePath), fileName)
Try something like:
string pathForSaving = Server.MapPath("~/Upload/Images");
string uploadFileName = System.IO.Path.GetFileName(image.FileName);
string uploadFilePathAndName = Path.Combine(pathForSaving, uploadFileName);
image.SaveAs(uploadFilePathAndName);
How are you setting shoe.ImagePath? Your issue feels like Server.MapPath is returning a value that you are not expecting.
Did you check to see if you have multiple web servers? Like a load balancer perhaps. It might not be throwing an exception because there isn't actually an exception and the file does actually exist somewhere, just not on the server you believe it is on. Just a thought (it has happened to me before).
Make sure you are using enctype="multipart/form-data" in the form
http://www.prideparrot.com/blog/archive/2012/8/uploading_and_returning_files
I also ran into the same issue posted on this thread and after a few tries of uploading a file, I refreshed the folder where the files were suppose to be and finally I saw them there. Not sure why it didn't show up the first time after the first refresh but it probably has something to do with refreshing the folder. I did the refresh from within Visual Studio and I also had the "Show All Files" button on.