Much time spent today grappling with the problem of applying a style to a file upload control on a website. The site application is ASPX pages with code behind in VB. The button controls on the rest of the site (whether asp controls or straight html) are styled with CSS. The new page I was adding as well as various other controls also needed to have the ability for the user client to upload a local file to the server, and then there would be some backend processing happening server-side.

It turns out that there is no simple way to apply a style to the button on an HTML Input type File tag - not surprising since the selection box and button are created client-side by the browser, and in fact different browsers implement it differently. The asp File Upload control is rendered on the client as a standard HTML Input tag with type=file, so even setting the CSSclass attribute doesn't really give you any flexibility. I wanted to be able to independently colour and position both the text box and the button.

You can apply a style to the whole control to set colour and font for the filename, but the text on the button ("Choose file" in Opera and Safari, and "Browse..." in Firefox) and the button appearance cannot be over-ridden.

OK, no problem - I am using the AjaxControl Toolkit anyway and there a couple of useful looking controls in that - AjaxFileUpload control and AsyncFileUpload control. Surely I can get them to do what I want.

The AjaxFileUpload control allows you to specify file type filter on the control and handles multiple files providing a drag and drop interface as well as a conventional file selector and also shows a progress bar (on HTML5 compliant browsers). Sounds ideal.

Of course the tutorial on the AjaxControlToolkit website has gone missing in action and most of the examples are in C# but that's not a problem. The problem is that try as I might I simply could not get the server side events to fire. After about an hour of trying various things and searching around I finally discovered a reference to a bug in the control whereby if it is displayed in a panel that is initially (on page render) hidden then the events never get triggered. Guess where my control was positioned - in an initially hidden panel of course because I didn't want the user to see it until it was appropriate. AAARGH.

No obvious way to workaround that within the spec. Making the panel not hidden caused the control to work, but that is not what I wanted.

Next up try the Async version. This, as its name implies, allows for asynchronous uploading of the selected file, allowing other stuff to happen in the meantime which could be useful. But it turns out that it is actually rendered on the client as a standard HTML Input type=file control (albeit with some fancy javascript wrapped around it) so we are back to square one - grrrrr.

OK lets bite the bullet and implement the hackish workaround that various people on t'internet have proposed. Essentially use the opacity of the input control to make it transparent, and then the z-index property to position a text box and a button underneath it.

Now the input control is effectively invisible but will still get any click events. Then you can use its onchange event to update the text in the visible text box underneath the control using javascript.

Once you've got your head around it its fairly straightforward. Just a matter of positioning the relevant controls in div tags so that they appear in the right place. You can even have the text box outside the input control so that clicking on it has no effect (or a different result).

In the onchange event for the input control you can add some preliminary screening for file type (but don't rely on this, you are simply checking that the file selected has the right extension, not a secure check against a malicious upload.

 

Tags:
Vb-net: