Have you ever had a WebDev site, that allows the user to upload and set the logo for their account? Have you had issues with the logo not changing when they upload a new one because of the browser cache? Well if so you are in luck, this week we will look at the pcReminder.com profile page, that allows the user to change their logo, and we will see how I beat the browser cache issue as well.
Higher level pcReminder accounts, can co-brand their reminders with their own logo. So I needed a way to allow them to upload their logo. Since these logos will be attached to emails, I am not storing the logo in a database, but am instead storing in a directory. So let’s take a look at the Account Settings Page.
BTW, for the lower level accounts I leave the fields visible, just disabled, and use the pcReminder logo. I want them to know what is available if they pay more!!
The upload button is the standard WB upload control. I am using the single file version.
Note: this control uses flash, which means it will not work for IOS devices, for now I have decided to live with that.
I removed the drop here static and changed around the controls a bit, to match the look and feel of the site. Next I placed an image control on the page.
The image control is set to Dynamic, with 100% display mode. It’s size is 140 x 70, which is the maximum size I allow logos to be, and it is not linked to any database field.
Now let’s look at the code behind the upload button. When you first populate the upload button it starts with a stub of some of this code for you. The first section of code we are going to look at is some browser code that first with the list of files to upload is modified, when you select a file or drop it on the upload here static. Since I removed the upload here static that doesn’t apply but the code is the same regardless
Line 1, test to insure there is a file to upload. The multiple file upload version shares the same events, which is why all the text is in plural, but for my purposes I am only supporting a single file.
Line 2 resets the progress bar, so it will be begin at 0.
Line 3 displays the cell containing the progress bar. When you populate the control the progress bar is in a cell, so you have to make sure to move it together.
And finally Line 4 begins the actual process of uploading the file to the server.
Next is a bit of browser code that updates the progress bar as the upload takes place. The functions are all standard WB functions, and in fact this code has not been changed from the default code that was populated with the button.
One final bit of browser code, to close the cell that contains the progress bar once the upload is completed.
And finally the workhorse of the upload logic, which is server code. Notice that it is AJAX enabled.
Lines 1,2, and 3 define some variables for later use.
Line 5, gets a random unique file name.
fTempFile() returns the file name including the temporary path. Since I need just the file name, I use ExtractString on Line 6, to get everything after the final in the file name. Notice I am using the FromEnd option to accomplish this.
Line 7 is another one of the standard upload commands, this copies the file, which at this point is in memory (I assume), to a location on the server. Notice it takes two parameters the directory and the file name, which is why I had to strip the directory off the file name.
Line 8 proves that a programmers job is never done, now I need the file name including the directory, so I “stitch” it back together.
Line 9 gets the size of the file, using the standard WX function fSize()
Line 10 gets a tab delimited string with information concerning an image file.
Line 11,12 and 13, use ExtractString to get the Format of the Image, and the Width and Height from the Tab delimited string.
Lines 14 – 22, do some error checking, I require that the logo be no more than 64K, 140 x 70 pixels, and in PNG format. I am very restrictive on the logo’s because of how they are used when sending out reminder emails.
If the code makes it to Line 23 then a valid upload has taken place. Ignore Line 23 for now we will come back to it later.
Line 24, moves the image file, from the temporary directory to a directory under my web folder, so that it is accessible from the web. I use the UserId of the logged in user to name the file, which makes my logic elsewhere simple.
Line 25, sets the Image control to the file we just placed under the web folder. If you inspect the image element via control you can see how this translates to the HTML code.
Note this is where working with images can be tricking, depending on if you are working with Server code, Browser code, and how the Image Control is configured, the resulting HTML code is completely different. That is why tools like Google Developer tools, or Firebug is so handy as it is easy to inspect the element and see how the code is being generated.
Finally Line 27, deletes the temporary file as it is no longer needed.
At this point the upload code works, there is a little bit of code to populate the image when editing a record, which we will look at shortly. But the actual upload is functional. However if you were to run the code, and upload a new image, you might not see the image change and think that you code is not working.
The issue is that the browser has cached the image. For instance, in the example the NextAge logo is displayed. If I upload a new logo, the NextAge logo continues to be displayed. However if I navigate to the cobrand folder, I will see that the image has indeed been uploaded.
If working on a remote site, that I didn’t have access to the drive directly I could have debugged it by inspecting the element, and copying the link address.
But note even pasting that link into the browser, shows me the “old” logo.
However, if I press Control F5, which forces chromes browser to refresh, I will see that the “new” logo.
Do to the nature of WebDev Dynamic sites, we can’t just do a Control F5 on the account profile page.
So we finally get to the meat of this article, how do you avoid this browser cache issue? I have tried several processes over the years, including such things as changing the name of the image, each time, which works but is a pain to code. Finally I think I have come up with the cleanest and least code intensive method of avoiding the cache issue. And it require one line of code to be changed!!!
On line 25, I have included some new text.
Now you know what Line 23 was for, I am generating a random number between 1 and 100, and placing it at the end of the file name. Those of you familiar with HTML code will recognize this as a URL parameter. Since the URL provided is an actual file name, the Image gets displayed, but because the entire text of the Image URL is slightly different the Browser Cache thinks that it is a different image and does not reuse the cache. PROBLEM SOLVED!!!
If you inspect the element now, you will see how our URL parameter is tacked on to the end of the image name, “confusing” the browser cache.
One last bit of code is needed to populate the image control when editing an existing record.
Once again I need a random number, which Line 6 takes care of.
Line 7, updates any linked fields and doesn’t effect our image control since it is not linked.
Line 8, is testing the users level of service, to determine how to handle the logo. Only our higher subscription levels are allowed to change their logo.
If the user does have a high enough level of service, I build the file name, using the UserID on Line 9.
On Line 10 I test to see if the Image exists, not all of our higher subscription level users, want to use a custom logo. If it does exists, I set the image control to that image file, again using the URL trick to avoid any cache issues, otherwise Line 13 displays the standard pcReminder logo, which is what will be on their reminders if they haven’t cobranded them.
And Line 16, displays the pcReminder logo for users that don’t have a high enough subscription level to use their own level.
Since I am storing a physical file, the save logic for the account profile doesn’t have to do anything related to the image.
As always I hope this inspires you or otherwise help you with your own adventure in WX.
Uncle Pete’s Corner is webinar series on all things WX, to watch the watch the Uncle Pete’s corner webinar that is the companion to this article, and many other WX related webinars go to the WinDev US YouTube Channel and be sure to also join the WxLive – US Communityon Google+ to get notices about upcoming webinars. On the Google+ community you will find a active group developers discussing all things WX.