Ajax File Upload Workaround in SharePoint 2010

Today I decided to post about a feature I developed this week. I’m currently working on a Social Project hosted on SharePoint 2010 and we are developing a WebPart to Post your status and share an optional image.

The WebPart must display an input file field to choose the picture to share and a preview must be displayed to the user before he decides to post his status. We are trying to avoid as much as possible PostBacks to offer an improved user experience.

The problem : How to post an input file dynamically without refreshing the entire page ?

My first idea was : with an Ajax call of course ! Unfortunately to do this you have to use the File API added to the DOM in HTML5, but guess what? Internet Explorer does not support this.

The workaround : posting the ASP .Net form into a hidden frame. The frame returns the image, then a script extracts it from the frame’s DOM and insert it into a container in the main page. Thanks to this only the frame is reloaded, this is transparent to the user.

The image is not saved in the server, all the operations occurs in memory, the goal is only to display a preview of the image. Of course you can modify my sample to save the image server side.

Downloading the solution

You can download the entire solution here : download solution.

You should be able to compile it without doing anything else but if you want to deploy it on your SharePoint environment you will have to sign-it with your key.

Step 1 – The project

Creates a new Empty SharePoint Project with Visual Studio, I choosed “Wawawum.DynamicUpload”. If you don’t already have JQuery deployed in your environment you can reuse my project “Wawawum.JQuery” and include it into your solution.

Then add a Visual WebPart “ImagePreviewWebPart” and add it to the Default Feature if it is not already included.

Map the “Layouts” folder to your project and add a new Application Page “PreviewImage.aspx” into it.


Your project tree should be like the screenshot above. Now we just have to fill the blanks Smile

Step 2 – The UserControl

Let’s create our controls that will post the image and display the preview. Add the following lines to your “ImagePreviewWebPartUserControl.ascx”:

This code is pretty straight forward but here is the goal of the controls:

  • ImageInput : the form field which will contains the path to the file to upload
  • ImagePreviewSubmit : the form button which submits the ASP .Net form into the iframe
  • ImagePreviewLoadingContainer : the div which displays a “Loading” message and image
  • ImagePreviewContainer : this div contains the preview of the image
  • ImagePreviewUploadFrame : the frame in which the form is posted. Using this iframe avoids the entire page to be reloaded when uploading the file.

Step 3 – Few lines of JavaScript

Now we need some JavaScript to post the ASP .Net form into the frame and retrieved the content of the frame to display it in the correct container. Add the following JavaScript block in the ImagePreviewWebPartUserControl after the HTML Controls.

Here are the main points of this script:

  • initImagePreview (line 7) : binds events to the controls. Notice that I used ASP .Net Inline Server Tags into my JavaScript to get the client ids of each controls. By using HTML Controls with the runat=’server’ attribute I’m sure to avoid conflicts when adding two instances of the same WebPart in a page.
  • imagePreview_onPreviewLinkClick (line 22) : called when the preview button is clicked. This function posts the ASP .Net form in the iframe. We have to modify the target and action attributes of the form to do that. The original values of these attributes are saved before posting and restored after.
  • imagePreview_onFrameLoaded (line 48) : called when the iframe is loaded. This function retrieves the img element generated by the browser (I tested it in Internet Explorer and Chrome and the code generated is compatible). Then this element is extracted from the frame DOM and added to the div “ImagePreviewContainer”.
  • ImagePreviewEventsArgs (line 63) : object used to pass the controls to the event handlers. The action field contains the server-relative URL of the Application Page which returns the Image.

Step 4 – Code behind

Almost all the code of the User Control is in the ASCX file but we need to set one attribute in the code-behind. So edit the code-behind of the ImagePreviewWebPartUserControl and add the following lines:

This code set a unique name to the iframe to avoid conflicts when multiple instances of the WebPart are added to the page.

Step 5 – The Application Page

The goal of this page is to receive the image posted by the UserControl, resize it and return it to display the preview image into the iframe. It is important to notice that it does not return some HTML but an Image, thus the content type of the response header will be “image/jpeg”.

Open the code behind of the “PreviewImage.aspx” page and here is what it should look like :

This code is very simple. The posted file is retrieved thanks to the Request.Files collection of HttpPostedFile. The file’s content type and size are checked, then in the Render method override the image is resized and written to the response.

Step 6 – Disable Message Authentication Check on the Application Page

The last thing we have to modify is the ASPX page. We need to set the “EnableViewStateMac” attribute of the Page directive to “false” to avoid the “This Page has been modified since you opened it. You must open the page again” error message.

In fact the PreviewImage page receives its form data from another page. In this data is included the ViewState of the WebPart page which causes this error. That’s the reason why we have to disable the message authentication check.

Step 7 – Build and Deploy

Finished. We just have to build the solution and deploy it. Then add the WebPart to a WebPart page and you should obtain this result :


Yes I know there is no design here. But that’s not the point of this article right? If you browse for a picture and click on preview you should see the loading message then the preview :


And the most important part is the preview displayed without refreshing the entire page.


We can’t really say that there is no postback here because the ASP .Net form is actually posted in the iframe but this is transparent to the user. A lot of JQuery plugins that use the File API of HTML5 fall-back to this method when Internet Explorer is the client.

So I thought interesting to demonstrate how to implement it in a SharePoint environment in spite of the fact that there is not really any SharePoint code here. You can reuse this code as-is but I strongly recommend you to add some validation logic, security and error handling.

I hope it helps you and feel free to comment.

4 thoughts on “Ajax File Upload Workaround in SharePoint 2010

  1. Hello mister !

    Ca a toujours l'air de rouler pour toi à Montréal 🙂
    Juste une petite question, l'image est stockée où une fois téléchargée ? Dans le contrôle ? Dnas une librairie ?

  2. Salut Thierry.
    Ouais ça va super à Montréal et toi?

    L'image est stockée nul part. Dans cet exemple mon but est simplement d'afficher un preview. Il faut donc reposter ensuite le formulaire pour publier l'image.

    L'image est simplement redimensionnée en mémoire puis le résultat est écrit dans la réponse de la page (en changeant le content type dans les Headers).

    On peut très facilement modifier le code à la ligne 33 du code de la page applicative (Step 5) pour sauvegarder le retour de ResizeImage dans SharePoint ou bien dans une BD externe ou même dans le cache IIS.

    L'intérêt de sauvegarder dans le cache (pour une durée courte de quelques minutes) serait de ne pas avoir à reposter le formulaire pour sauvegarder l'image.

    Dans ce cas l'utilisateur sélectionne son image, poste le formulaire en faisant 'Preview'. L'image est redimensionnée, cachée côté serveur et retournée à l'utilisateur. Ensuite quand l'utilisateur décide de publier, le formulaire ne poste pas l'image mais seulement les informations permettant de retrouver l'image dans le cache d'IIS et on peut alors persister les données.
    Cela permet simplement de gagner du temps pour l'utilisateur, aucun intérêt dans un contexte d'intranet évidemment.

  3. Ca va très bien avec le printemps et les temperatures qui remontent 🙂

    Ok pour le stockage. Ca m'amène à poser une autre question du coup : si on a plusieurs WFE, et que par soucis de charge ou autre, le load balancer decide de changer de serveur, n'auras tu pas un problème pour afficher l'image ?

    Et aussi juste une petite idée pour le test des MIME Types : http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.administration.spwebapplication.allowedinlinedownloadedmimetypes.aspx.

    Tu imagines que je ne pose pas ces questions par hasard 😛 Ca correspond en partie au besoin d'un client ! C'est pour ca que ça m'intéresse 🙂


  4. Dans l'exemple où l'image n'est pas stockée (version preview uniquement) il n'y a pas de problème avec les WFE puisque la durée de vie de l'image ne dépasse pas celle de la requête.

    Dans le cas où tu souhaites stocker l'image alors effectivement il va falloir se poser la question.
    Ce qui me vient à l'esprit serait de faire un répertoire d'upload à la racine de ton SPWeb.
    Une fois l'image récupérée côté serveur tu sauvegardes dans le répertoire en question. Il n'y a plus de problème concernant les WFE étant donné qu'on est dans la Content DB de SharePoint.

    J'utiliserais donc : http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spweb.files.aspx

    Au lieu de retourner l'image directement tu peux alors retourner du HTML avec le lien vers l'image dans le répertoire d'Upload (si tu es à l'aise avec le fait que tout le monde pourra voir les uploads de tout le monde). Si tu as besoin de sécurité alors il faut continuer à retourner l'image et sécuriser le répertoire d'upload (il faudra alors utiliser un RunWithElevatedPrivileges).

    Le problème de ce système c'est que les images ne vont pas se supprimer toutes seules.
    – On peut les supprimer du répertoire d'upload pour quand l'utilisteur décide finalement de publier l'image.
    – Il faut ajouter un timer job qui va venir nettoyer les fichiers qui ont plus de x minutes.
    – Il faut gérer le UI pour supporter le cas où un utilisateur rafraichit son preview alors que l'image vient d'être supprimée par le timer job.

    Si le timer job te semble trop lourd d'un point de vue maintenance alors l'autre solution consiste à synchroniser les caches des WFE.
    J'ai déjà utilisé un principe similaire pour supprimer le cache de tous les WFE. Ce serait le même principe.
    Il faut créer une page applicative qui met à jour le cache et appeler cette page avec les bonnes données (en POST) pour chaque WFE.
    Dans ce cas on synchroniserait le cache pour avoir le preview de l'image sur tous les WFE.
    Cette technique fonctionne mais à priori c'est quand même le timer job qui me semble la meilleure solution. L'autre c'est un peu trop "bricolage" à mon gout.

    Pour les MIME types je ne connaissais pas cette propriété. Effectivement ça peut être une bonne solution pour coller avec les settings de SharePoint. Dans mon cas je veux uniquement les images donc il faut quand même limiter un peu plus les content types disponibles.

Leave a Reply

Your email address will not be published. Required fields are marked *