Accessing the local file system in Silverlight 3

2. november 2009

One of the problems with Silverlight applications as opposed to regular desktop applications is that their access to the local file system is extremely limited. In Silverlight versions 1 and 2 you could only access if via the Isolated Storage system, and that only allowed you to store up to 1 Mb of data per default. If you wanted to store more than that you had to ask the user to increase your quota.

The reason for this is of course security. If Silverlight applications were allowed access to the file system per default you could create a transparent application that searched all the files on the users computer and did whatever you wanted with it.

This limitation meant that you had to do some serious hacking if you wanted to let the user create content in a Silverlight application that he could store locally. One way is to post the data to an asp-page that will return the file for the browser to save, but that is both clumsy and inefficient.

In Silverlight 3 the situation has changed somewhat. You still cannot access the local file system directly, but you can use the OpenFileDialog to let your user browse to a file that you can then read. You also have the SaveFileDialog that lets your user select a file that you can write to. You still don’t have full access to the file system, but at least you have a way to load and save files.

The OpenFileDialog class should be well known if you have done windows programming in WinForms or WPF. It allows you to specify the file extension of the file you want to open before displaying the dialog. If the user selects a file you get a reference to the file as a FileInfo object that you can read using the OpenRead or OpenText methods.

The SaveFileDialog is similar to the OpenFileDialog in that it allows you to specify a file extension before displaying the dialog. If the user selects a file name you will get a Stream object that you can write to using the OpenFile method.

But, enough chat. Lets look at some source code! This first example opens a text file for reading:

private string OpenFileAndReturnContentAsString()
{
   OpenFileDialog openDialog = new OpenFileDialog();
   openDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*";

   bool? result = openDialog.ShowDialog();

   if (result.Value)
   {
      using (StreamReader fileReader = openDialog.File.OpenText())
      {
         return fileReader.ReadToEnd();
      }
   }

   return string.Empty;
}

There are a few things to note here:

  • The format of the file extension filter should be well known to most, but it is rather clumsy to edit.
  • The ShowDialog will display the dialog as a modal window. It returns a nullable boolean that will always contain either True or False. If the user selected a file the value is True and if he cancelled the dialog or closed the window the value will be False.
  • The File-property of the OpenFileDialog object is a FileInfo that refers to the file. We can access some of its properties, but most are unavailable due to security restrictions. The only really useful property you have access to is Name. The Directory, DirectoryName and FullName properties are unavalable.
  • The FileInfo class has two methods that you can use to access the file. The OpenText method returns a StreamReader object that you can use to read the file as text. Alternatively you can use the OpenRead method to get a FileStream that you can read.

To write files you must use the SaveFileDialog:

private void SaveTextFile(string content)
{
   SaveFileDialog saveDialog = new SaveFileDialog();
   saveDialog.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*";<

   bool? result = saveDialog.ShowDialog();

   if (result.Value)
   {
      using (Stream saveStream = saveDialog.OpenFile())
      using (StreamWriter saveWriter = new StreamWriter(saveStream))
      {
         saveWriter.Write(content);
      }
   }
}

The code here is somewhat simpler than for opening files, the main reason being that you only have one way to access the file you want to write to. There are a few points to make here as well:

  • The filter is the same as the one used in the OpenFileDialog example.
  • The ShowDialog method also works the same way as for the OpenFileDialog.
  • The only way to access the file is to use the OpenFile method. This returns a Stream that we can write to.
  • When writing a text file it is easier to wrap the Stream in a StreamWriter and use that instead.
  • If you need to know the name of the file you are writing to you can use the SafeFileName property of the SaveFileDialog. This gives you the file name only, not the directory name.

I have attached a sample project. This is a simple text editor where you can load and save files locally. The solution is a Visual Studio 2010 b2 file, but the source code (xaml- and cs-files) should compile just as well in Visual Studio 2008.

Feel free to comment if you have anything to say! :-)

SLFileSystem.zip (58.00 kb)

kick it on DotNetKicks.com

Silverlight, .NET ,