File Upload Control Using Silverlight

Uploading files in web application is always a big trouble. We need to take care of the file size before upload the files into the server. And to check the file size at client side itself, we need to go for ActiveX controls which is not secured and also not cross browser supported. The same will be a big issue for Multiple file upload control. So, I have used Silverlight controls for uploading files. The files transfer will be taken care of by Webservices.

Here is the Code for the controls....

XAML

<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"  xmlns:basics="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"  x:Class="SilverlightApplication1.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="600" Width="800" >

    <Grid x:Name="LayoutRoot" Background="YellowGreen" ShowGridLines="True" >
        <Grid.RowDefinitions>
            <RowDefinition Height="535"></RowDefinition>
            <RowDefinition Height="30"></RowDefinition>
            <RowDefinition Height="35"></RowDefinition>
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="2" Orientation="Horizontal" >
            <Button Content="Choose File" x:Name="MyButton" Width="100" Height="20" Click="Mybutton_Click" Grid.Column="0"></Button>
            <Button Content="Reset" x:Name="MyReset" Width="100" Height="20" Click="MyReset_Click" Grid.Column="1"></Button>
            <Button Content="Upload" x:Name="Upload" Width="100" Height="20" Click="Upload_Click"  Grid.Column="2"></Button>
        </StackPanel>
        <StackPanel Grid.Row="1" VerticalAlignment="Center">
          <ProgressBar Name="progFile" Height="20" Width="800"></ProgressBar>
        </StackPanel>
        <Grid Grid.Row="0">
            <data:DataGrid Name="FileList" LoadingRow="DataGrid_LoadingRow">
            </data:DataGrid>
        </Grid>
     </Grid>

</UserControl>


you can see that you have three buttons,
1.Choose File   - to borwse the file using file upload dialog
2. Reset - to remove all selections of files
3. Upload - to upload the selected files into the server

and one datagrid, to show the list of selected of files on the fly...
here is the screen  shot for this

and one progress bar to show the progress of the file uploading...



 
When ever you select the Choose file button, it will show the file browser dialog and you can select files from client file system. I have checked the individual file limit as 1MB.

I have used the class file to store the file related informations. For each file I have created one file class object and I added the file object to Arraylist.

here is the file class code

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.IO;

namespace SilverlightApplication1
{
    public class FilesClass
    {
         public FilesClass()
        {
             //do nothing
        }

         string strStatus = "";
        string strNo = "";
        FileInfo strFileName = null;

        //for file serial number
        public string PropNumber
        {
             get
             {
                  return strNo;
            }
            set
            {
                strNo = value;
            }
        }

         //to store the file
        public FileInfo PropFileName
        {
            get
            {
                 return strFileName;
            }
            set
            {
                strFileName = value;
            }
        }

       //to store the status, whether file uploaded successfully or not  
        public string PropStatus
        {
             get
             {
                  return strStatus;
            }
            set
            {
                strStatus = value;
            }
        }
    }
}







and here is the Choose button click event code..

private void Mybutton_Click(object sender, RoutedEventArgs e)
        {
            //show the file browser dialog to select file
            OpenFileDialog op = new OpenFileDialog();
             op.ShowDialog();
             if (op.File != null && op.File.Name != "")
            {
                 //check the file size. It shoud be less than 1MB
                 if (op.File.Length < 1048576)
                 {
                      //flAll[iFileCount] = op.File;
                     //fl.Add(op.File);
                     
                      //create a new fill class object to maintain the file content    
                    FilesClass obj = new FilesClass();
                   //assign file  
                    obj.PropFileName = op.File;
                     //assing file number
                    obj.PropNumber = iFileCount.ToString();
                     //add the file object to files list collection  
                     fl.Add(obj);

                      //flNames.Add(op.File.Name);
                     
                      //update the grid with new files
                     BindGrid();

                      iFileCount++;
                 }
                  else
                 {
                     MessageBox.Show("Max file size is 1 MB");
                 }
             }
             else
            {
                 MessageBox.Show("Select File");
            }
        }

         
         //Code to bind the grid  
        private void BindGrid()
        {
            FileList.ItemsSource = null;
            //setting datasource for datagrid FileList
            FileList.ItemsSource = fl;
            FileList.SelectedIndex = -1;

             //for grid object with column header and column width
            FileList.Columns[0].Header = "S.No";
            FileList.Columns[1].Header = "File Name";
            FileList.Columns[2].Header = "Status";


            FileList.Columns[0].Width = new DataGridLength(80);
            FileList.Columns[1].Width = new DataGridLength(600);
            FileList.Columns[2].Width = new DataGridLength(100);
        }



so, when ever you select the file in browser control, it will be added to datagrid ... and you can able to see the list of selected files..

I have used Webservice to upload the file from client to server...

here is the code for this Web service


 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.IO;

namespace SilverlightApplication1.Web
{
    /// <summary>
    /// Summary description for uploadService
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
    // [System.Web.Script.Services.ScriptService]
    public class uploadService : System.Web.Services.WebService
    {

        [WebMethod]
         public string HelloWorld()
        {
             return "Hello World";
        }

//method for uplaod the files. This will be called from Silverligh code behind.
        [WebMethod]
         public string UploadFiles(string strFileName, byte[] byFile, string strFileNo)
        {
             try
            {
                 if (byFile.Length > 0)
                 {
                      string strFilePath =
"D:\\tmp\\" + strFileName;
                    System.IO.FileStream fs = new FileStream(strFilePath, FileMode.Create, FileAccess.Write);
                    fs.Write(byFile, 0, byFile.Length);
                    fs.Close();
                    return strFileNo;
                }
                else
                {
                    return "
";
                }
            }
            catch(Exception ex)
            {
                return "
";
             }
        }
     }
}


I am pasing file Name, file content as byte and file Number(serial number). Serial number will be return back to
calling method to confirm that file uploaded successfully. As we are using Asynchronous file upload,
we need to know which file is uploading. for this I am using strFileNo in UploadFiles method.


and here is the main code for uploading files...


//we need to add web serice as Service reference in application.

//to show the progrss bar
double progVal = 0;

        private void Upload_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                 if (fl.Count > 0)
                {
                    progVal = (double)100 / (double)fl.Count;
//loop through the files and upload the files by passing it to web service.

                     for (int count = 0; count < fl.Count; count++)
                    {
                       ServiceReference1.uploadServiceSoapClient x = new SilverlightApplication1.ServiceReference1.uploadServiceSoapClient();

//here is the event hadndler, whihc will be invoked for every file upload
                        x.UploadFilesCompleted += new EventHandler<ServiceReference1.UploadFilesCompletedEventArgs>(UploadFileComplted);

//read the file from file class

                        FilesClass obj = (FilesClass) fl[count];
                        System.IO.FileStream str = obj.PropFileName.OpenRead();
                          byte[] by = new byte[str.Length];
                        str.Read(by, 0, by.Length);
                          str.Close();
//call the upload file methods async event, which will upload the files asynchronously
                        x.UploadFilesAsync(obj.PropFileName.Name, by, obj.PropNumber);
                        progFile.Value += progVal;

                     }
                 }
             }
             catch (Exception ex)
             {
                 MessageBox.Show(ex.Message);
             }
         }


and once the file upload complted, it will invoke the uploadfilecomplted event...



private void UploadFileComplted(object sender, ServiceReference1.UploadFilesCompletedEventArgs e)
         {
             if (e.Result != "")
            {
               //here e.Result contains the files serial number. We can change the status the file class object based on this.
                fl[Convert.ToInt32(e.Result) - 1].PropStatus = "1";
                 BindGrid();

            }
        }



and to change the uploaded files status in grid, we need to use the loading row event. Depends upon the status field value, the rows back color will be changed

private void DataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
        {
            FilesClass obj = e.Row.DataContext as FilesClass;
             if (obj.PropStatus == "1")
            {
               e.Row.Background = new SolidColorBrush(Colors.Gray);
            }
        }


I know it will be hard to undestand the above things with out live deme... here I have attached the full sample for your better understanding...

WebSite:
http://www.eggheadcafe.com/fileupload/-1661267333_SilverlightApplication1.Web.zip

Silverlight application:
http://www.eggheadcafe.com/fileupload/-1661267333_SilverlightApplication1.zip

By Vasanthakumar D   Popularity  (15196 Views)