Tags

, , ,

When you search for custom solutions to upload files to SharePoint, you will probably be advised to use REST API offer by SharePoint 2013, which is fine. The reason why people advise you so is mainly because CSOM is not able to upload files larger than 2Mb. Which is partial true. There is a solution to upload large files using CSOM and I will show you below how to do it.

Solutions I choose is based on Silverlight. I know you will tell me it is obsolete. But for the moment is still on the market, available at least till 2021 and is sometimes a good solution. So I see no reasons why you cannot use it. So what I achieved looks like below and if you like what you see, continue to read. ๐Ÿ™‚
Silverlight Uploader

Solution markup

Solution contains a textbox, where selected file name will be display, a label to display error or success message, a button to open file dialog window to choose the file you want to upload and another button to start upload process. Without too many comments, here is the markup.

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit" x:Class="HPFileUploader.MainPage"
    mc:Ignorable="d" Height="113" Width="800">
    <toolkit:TwilightBlueTheme  HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top">
        <Grid x:Name="LayoutRoot" Background="White" Margin="0,4,0,0" Height="113" VerticalAlignment="Top" Width="800">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="13*"  />
                <ColumnDefinition Width="787*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>

            <Button Content="Choose" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Left" Margin="225,10,0,0" VerticalAlignment="Top" Width="75" x:Name="btnUpload" Click="btnUpload_Click" RenderTransformOrigin="0.52,-0.864"/>
            <TextBox  Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" IsReadOnly="True"  x:Name="txtFileName" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="220" Grid.ColumnSpan="2"/>
            <Button Grid.Column="1" Grid.Row="0"   Content="Start Upload" HorizontalAlignment="Left" Margin="305,10,0,0" VerticalAlignment="Top" Width="92" x:Name="startUpload" Click="startUpload_Click"/>

            <sdk:Label HorizontalAlignment="Left" x:Name="lblError" VerticalAlignment="Center" VerticalContentAlignment="Center" Height="28" Margin="0,11,0,17" Grid.Row="1"  Width="680" Grid.ColumnSpan="2">

            </sdk:Label>
      </Grid>
    </toolkit:TwilightBlueTheme>
</UserControl>

Add SharePoint client reference

If you choose to create a standalone Silverlight project, you will need to add some libraries and references to your project. The easiest way it to you use NuGet and add Microsoft SharePoint Foundation 2010 Client Object Model package.
FileUploader - Manage NuGet Packages

Once you add the package you need to be sure the following references are set.
2015-01-28 22_00_52-HPFileUploader - Microsoft Visual Studio (Administrator)

Code behind

And here is essence of this article.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.SharePoint.Client;
using System.IO;
using System.Text;
using System.Xml.Linq;
using System.Windows.Browser;


namespace FileUploader
{
    public partial class MainPage : UserControl
    {

        private FileStream fs;
        private string fName = "";

        public MainPage()
        {
            InitializeComponent();
        }

        /// <summary>
        /// This method is handling click even for choose file button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnUpload_Click(object sender, RoutedEventArgs e)
        {

            this.lblError.Content = "";            

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

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

        /// <summary>
        /// Start upload button click
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void startUpload_Click(object sender, RoutedEventArgs e)
        {
            if (this.fs == null || this.fName == "") return;

            using (ClientContext ctx = new ClientContext("https://sharepoint"))
            {

                this.btnUpload.IsEnabled = false;
                this.startUpload.IsEnabled = false;
                this.startUpload.Content = "Wait...";

                Web web = ctx.Site.RootWeb;
                List oList = web.Lists.GetByTitle("Attachments");
                FileCreationInformation fci = new FileCreationInformation();
                fci.ContentStream = fs;
                fci.Overwrite = true;
                fci.Url = "https://sharepoint/Attachments/" + fName;
                Microsoft.SharePoint.Client.File file = oList.RootFolder.Files.Add(fci);
                ctx.ExecuteQueryAsync(
                    (object s, ClientRequestSucceededEventArgs args) =>
                    {
                        this.Dispatcher.BeginInvoke(() =>
                        {
                            this.lblError.Content = "File was upload succesfully";
                            this.txtFileName.Text = "";
                            this.fName = "";
                            this.fs = null;
                            this.btnUpload.IsEnabled = true;
                            this.startUpload.IsEnabled = true;
                            this.startUpload.Content = "Start Upload";
                            HtmlPage.Window.Invoke("RefreshFilesList");
                        });
                    },
                    (object s, ClientRequestFailedEventArgs args) =>
                    {
                        this.Dispatcher.BeginInvoke(() =>
                        {
                            this.lblError.Content = "Request failed. " + args.Message + "\n" + args.StackTrace;
                        });
                    }
               );
            }
        }
    }
}

I am not going to explain all the code, but I will tell you what exactly is doing the trick. Giving a general example, the essence of the code can be reduced to this:

       // Create file stream and file name variables
        FileStream fs;
        String fName;

        // Create file dialog and use to assign value to the variable
        OpenFileDialog dlg = new OpenFileDialog();
        dlg.Multiselect = false;

        if (dlg.ShowDialog() == true)
        {
            fs = dlg.File.OpenRead();
            fName = dlg.File.Name.ToString();
            this.txtFileName.Text = fName;
        }

        // Upload file
         using (ClientContext ctx = new ClientContext("https://sharepoint"))
         {
            Web web = ctx.Site.RootWeb;
            List oList = web.Lists.GetByTitle("Attachments");
            FileCreationInformation fci = new FileCreationInformation();
            // Here is the magic. Set ContentStream property of FileCreationInformation before execute query is doing the trick
            fci.ContentStream = fs;
            fci.Overwrite = true;
            fci.Url = "https://sharepoint/Attachments/" + fName;
            Microsoft.SharePoint.Client.File file = oList.RootFolder.Files.Add(fci); 
            ctx.ExecuteQueryAsync(success, fail) ;
         }  

I hope this will help. Happy coding! ๐Ÿ™‚

Advertisements