Tags

, ,

This is post is intended to respond to all developers who need a custom upload control. Majority of the solutions on internet are server side related, but in some cases only client side is allow and SharePoint Designer is the only tool you have.  The solution is a small Silverlight application which is able to convert a file into a byte array and pass it as encoded string to web service.

For the beginning, we need to create a class to read file from computer and transform it to base64 encoded string. The code below should do the work for you.

using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.ComponentModel.DataAnnotations;
using System.Windows.Documents;

public class FileUpload
{
        BinaryReader reader;
        long fileSize;

        /// <summary>
        /// Initialize FileUpload class
        /// </summary>
        /// <param name="fs">FileStream</param>
        /// <param name="size">Size of file</param>
        public FileUpload(FileStream fs, long size)
        {
            reader = new BinaryReader(fs);
            fileSize = size;
        }

        /// <summary>
        /// Read stream and convert it into base64 encoded string
        /// </summary>
        /// <returns>Base64 encoded string</returns>
        [ScriptableMember()]
        public string ReadFully()
        {
            byte[] output = new byte[fileSize];
            for (long i = 0; i < fileSize; i++)
            {
                output[i] = reader.ReadByte(); //read until done
            }
            return Convert.ToBase64String(output);
        }

}

As we need to use some JavaScript functions here, we can create a static C# class to invoke these. This would make usage of JavaScript easier.

using System;
using System.Net;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;

public static class JavaScriptInvoker
{
        /// <summary>
        /// Calling a javascript simple function without parameters
        /// </summary>
        /// <param name="fName">Function name</param>
        public static void Call(string fName)
        {
            try
            {
                HtmlPage.Window.Invoke(fName);
            }
            catch (Exception ex)
            {
                JavaScriptInvoker.Alert(ex.Message.ToString());
            }
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="fName"></param>
        /// <param name="fParams"></param>
        public static void Call(string fName, string[] fParams)
        {
            try
            {
                HtmlPage.Window.Invoke(fName, fParams);
            }
            catch (Exception ex)
            {
                JavaScriptInvoker.Alert(ex.Message.ToString());
            }
        }

         /// <summary>
         /// Display an alert message in window
         /// </summary>
         /// <param name="message">Text to be displayed in alert</param>

        public static void Alert(string message)
        {
            HtmlPage.Window.Alert(message);
        }
}

The interface is simple. It contains a textbox and two button. Textbox (name:FileName) is displaying file name, browse button (name:UploadFile) opens file dialog picker and upload button (name:btnUpload) starts upload operation.

Silverlight upload

Here is the source for this page (MainPage.xaml).

public partial class MainPage : UserControl
{

        private FileStream fs;
        private string fName = "";

        public MainPage()
        {
            InitializeComponent();
        }

        // Browse for file to upload
        private void UploadFile_Click(object sender, RoutedEventArgs e)
        {

            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Multiselect = false;

            if (dlg.ShowDialog() == true)
            {
                fs = dlg.File.OpenRead();
                fName = dlg.File.Name.ToString();
                this.FileName.Text = fName;
            }
            else
            {
                fs = null;
                fName = "";
                this.FileName.Text = fName;
            }
        }

        private void btnUpload_Click(object sender, RoutedEventArgs e)
        {
            if ((this.fs != null) && (this.fName != ""))
            {
                App myApp = App.Current as App;

                FileUpload uploader = new FileUpload(this.fs, fs.Length);
                JavaScriptInvoker.Call("AttachFile", new string[] { myApp.SPListItemId, myApp.SPListName, this.fName, uploader.ReadFully() });
            }
        }

 }

SPListeItemId and SPListName are initiation parameters and be passed from dataformwebpart. AttachFile is JavaScript function accept list id, list item id, attachment file name and file base64 encoded as parameters and consume lists.asmx web service, using AddAttachment method.

Advertisements