Friday, 5 September 2014

Check File Size on Upload in Visualforce

When uploading a file via the Visualforce apex:inputFile standard component, if the file size exceeds the particular Salesforce limit (e.g. uploading an attachment greater than 25Mb in size), the first the user knows about this is after the file has been uploaded to the server and an attempt is made to insert it into the database.  In the event of a large file over a slow connection (exactly the type of connection I am using to write this post from the North Norfolk coast), this isn’t the greatest user experience.

A better way would be to check the size of the file can be handled on the server prior to starting the upload.  Up until a few years ago, this wasn’t possible using regular HTML and JavaScript, instead something like a flash plugin was required. The advent of HTML5 introduced the File API, which provides access to the file and its metadata directly in the browser.

To demonstrate this I have a simple page that uses the account standard controller, with an extension controller to insert the attachment.  The page displays the current set of attachments associated with the record and a button to allow a new attachment to be uploaded:

Screen Shot 2014 09 05 at 17 21 19

Clicking the upload button and selecting a file larger than 25Mb (a 120Mb+ movie in this case), cancels the form submission and pops up an alert explaining the problem to the user:

Screen Shot 2014 09 05 at 17 25 33

As I’m on a slow connection, I’ve also added a warning when the user chooses a file that is over 2Mb in size - in this case they have the option to continue, on the understanding it may take a while:

Screen Shot 2014 09 05 at 17 25 52

The file checking is carried out in JavaScript, from an onclick handler on the ‘Upload’ button:

function checkFileSize()
{
    var goodSize = true;
    $('input[type=file]').each(function()
    {
        if(typeof this.files[0] !== 'undefined')
        {
            var file = this.files[0],
                size = typeof ActiveXObject !== 'undefined' ?
                    getIEFileSize(file)
                    :
                    file.fileSize || file.size;

            goodSize = 25000000 > size;
            if(!goodSize)
            {
                alert(this.files[0].name +' is too large - please choose a file that is 25Mb or less');
            }
            else
            {
            	if (2000000 < size)
            	{
                    goodSize=confirm('The file size is ' + size +
                    	' bytes - this may take some time. Are you sure you wish to continue');
                }
            }

            return goodSize;
        }
    });
    return goodSize;
}

This function uses JQuery to iterate the file elements on the page (one in this case), and for each input, gets the first (and only) file chosen.  the call to getIEFileSize allows this page to work with Internet Explorer prior to version 10, although I haven’t tested this recently, as I only use Macs these days. For non-IE browsers, the size is determined by the filesize or size properties (filesize is deprecated now, but its always a good idea to allow for older browsers!).  

The rest of the function simply checks the size of the file and generates an alert or confirmation dialog box as required.  Finally, a true/false result is returned to the onclick handler - if false, the form submission will be cancelled.

You can access the full page here, and for the sake of completeness, the full controller here.

4 comments:

  1. Hi bob ji i have one small requirement in visualforce pages We need a mechanism to read the file that will be a placed in a folder by a vendor and upload the data into Salesforce. It could be a script or any other options if they exist.

    ReplyDelete
  2. Hai all,
    I am creating a Visualforce page to upload photos and these photos are saved in the attachments object.How can i Upload Image(above 1MB to 10MB) Attachments to Salesforce using Javascript Remoting

    ReplyDelete