Azure, best way to store and deploy static content (e.g. images/css)?
Asked Answered
M

3

31

We're about to deploy our .NET web application to an Azure Web Role. I'm just wondering how others have handled their static content, specifically images and css? At the moment our application package is about 25mb but 18mb of that is derived purely from images, things like navigation buttons, icons and template components that rarely ever get updated. Would it be wise to partition this out of the deployment package and move it to blob storage?

I have a few doubts about this approach that I'm wondering are valid...

  1. 80% of our site runs in a HTTPS environment. Will accessing images in a blob store introduce cross-scripting problems?

  2. Vulnerability to money leakages, if someone tries to maliciously hammer our images (most are under 20kb)?

  3. I'm struggling to see how it's possible to upload files to a blob container (from VS2010 + Azure SDK) with directory naming convention so I don't need to rewrite 1000s of path references? I appreciate directories are an abstract concept in blob containers, but I can write files with a forward slash to imitate this in code. Obviously Windows does not allow me to do this before I upload in Visual Studio.

Any thoughts or alternative strategies would be welcome. The goal really is to shrink our deployment package to speed up the deploy time. Also I quite like the idea of offloading the image serving to a dedicated node to improve the performance on the web server, maybe my image collection is so small that it's hardly worth bothering?

Update 16th May ------------------------------------------------------------------------

Here's what I did in the end:

1.Transferred all images + css to blob storage containers. I maintained the structure of any sub-directories within the images and css folders.

2.Applied a URL Rewrite rule in our web.config file as follows..

  <rewrite>
    <rules>
      <rule name="imagestoazure">
      <match url="images/(.*)" />
      <action type="Redirect" url="https://xxxxx.vo.msecnd.net/images/{R:1}" />
    </rule>
  </rules>
  </rewrite>

3.Excluded the images + css folders from the application and deployed.

My deployment is now much smaller and the images are running off a CDN freeing up bandwidth, improving downloads speeds and releasing some load off the web-server.

Update: September 2015

When reviewing this recently I came across the following guide from Microsoft. It goes into more detail about how you can automate the deployment of your assets and cache bust using querystrings.

Serve Content from Azure CDN in Your Web Application

Micmac answered 5/3, 2013 at 11:56 Comment(3)
URL rewrite will redirect the Client to the corresponding blob.But Request is anyway coming to Web Server and consuming the Network resources. Is there any way If we can at run time change the Static content URL from relative to Blob URI.Mehalek
Regarding your update, how are you uploading/syncing your assets to blob storage. Is it part of your deployment process? Also, are you cache-busting the paths to static files? ThanksFrustration
Manually using Azure Management Studio. In the end we only moved images into the CDN, solving the bandwidth issue. All our buttons were gif based but over the years we've moved to CSS buttons and vectored icons. Now we may have one new/modified image per month, so no automated routine needed. I suppose you could automate the deployment, take a look here under "Automate content upload" azure.microsoft.com/en-us/documentation/articles/…Micmac
M
15

Some comments:

Would it be wise to partition this out of the deployment package and move it to blob storage?

Absolutely. I can see many benefits of doing this:

  1. As you mentioned, this would reduce your package size considerably thus deployment becomes much faster.
  2. Again as you mentioned, it would take the load off of your web server thus will make your site more responsive.
  3. If you need to update images, js, css files you can just replace those files in blob storage. If they were left in your package, you would need to redeploy your package.
  4. You could also take advantage of Windows Azure CDN which works off of blob storage.

80% of our site runs in a HTTPS environment. Will accessing images in a blob store introduce cross-scripting problems?

As long as you're not reading the contents through AJAX, I don't think you'll run into cross-scripting issues (How to access XML hosted as azure blob from azure website). However if your page is served via https and you reference static resources via http, your users might get mixed content (secured and unsecured) message.

Vulnerability to money leakages, if someone tries to maliciously hammer our images (most are under 20kb)?

Do take a look at the outbound bandwidth pricing here: http://www.windowsazure.com/en-us/pricing/details/#header-11. Currently Windows Azure is running a promotion where up to 5 GB of data transfer out is free and it's $0.12 / GB which is quite cheap. You would also need to take storage transactions into consideration which is also very cheap. I wouldn't worry too much about it. In the worst case scenario, you could always revert to shared access signature and protect the resources.

I'm struggling to see how it's possible to upload files to a blob container (from VS2010 + Azure SDK) with directory naming convention so I don't need to rewrite 1000s of path references? I appreciate directories are an abstract concept in blob containers, but I can write files with a forward slash to imitate this in code. Obviously Windows does not allow me to do this before I upload in Visual Studio.

There're a number of 3rd party tools available to you which will preserve the folder structure of your local computer when uploading in blob storage. Do take a look at this blog post from Windows Azure Storage team: http://blogs.msdn.com/b/windowsazurestorage/archive/2010/04/17/windows-azure-storage-explorers.aspx. Obviously my personal favorite is Cloud Storage Studio from Cerebrata :) [I'm one of the devs for that product]

Mariannemariano answered 5/3, 2013 at 13:53 Comment(3)
Excellent, thank you for the in-depth reply! I'll certainly take a look at Cloud Storage Studio, it looks like it will be useful with the directory structures we have in the images folder. Much appreciated!Micmac
Hi Gaurav, I'm testing Cloud Storage Studio now..it looks great! One thing I do need to be careful with is the case-sensitivity in the images paths. Fortunately your application seems to preserve this!Micmac
Hi, I like the idea of moving to blob storage. 1 question remains for me: how do I have my website translate all the image urls from (e.g.) ~/images/1.jpg to https://<path-to-blob-container/images/1.jpg ?Dryly
A
4

If your package is growing too big in size, maybe you can benefit from deploying standalone files, instead of a big single package file. At least in Visual Studio 2012, the Publish Wizard has now this deployment options:

  • Web Deploy (I encourage this you one)
  • Web Deploy Package
  • FTP
  • File System

AFAIK, Web Deploy compares source and target files, physically transfering only the different files (It probably compares files hashes, but I don't know about the internals).

Anyhow, I will try to give some more info to solve your questions:

80% of our site runs in a HTTPS environment. Will accessing images in a blob store introduce cross-scripting problems?

Gaurav Mantri already answered this, but just to provide a bit of more recent info, HTTPS is now supported for accessing Azure CDN, so you could avoid Mixed Content message. (Still pending support for custom domain/SSL Certificate (UserVoice request with latest info here).

By the way, using the protocol-less convention ( ://{domain}/{relative path}) the browser will use exactly the same protocol HTTP or HTTPS as the base document.

I'm struggling to see how it's possible to upload files to a blob container (from VS2010 + Azure SDK) with directory naming convention so I don't need to rewrite 1000s of path references? I appreciate directories are an abstract concept in blob containers, but I can write files with a forward slash to imitate this in code. Obviously Windows does not allow me to do this before I upload in Visual Studio.

Syncing static files to blob

One scriptable option for syncing your static files is the AZCopy tool.

An alternative is this powershell script (more info on this post), which, summarizing:

  1. Does the initial setup:

    $context = New-AzureStorageContext ` 
        -StorageAccountName $StorageAccount ` 
        -StorageAccountKey (Get-AzureStorageKey $StorageAccount).Primary
    
  2. Enumerates all local files on .\Content and .\Scripts:

    $files = (ls -Path $ProjectPath\Content -File -Recurse) + (ls -Path $ProjectPath\Scripts -File -Recurse)
    
  3. ...and uploads each file on a loop:

    foreach ($file in $files)  
        { 
            $blobFileName = (Resolve-Path $file.FullName -Relative).TrimStart('.') 
            $contentType = switch ([System.IO.Path]::GetExtension($file)) 
            { 
                ".png" {"image/png"} 
                ".css" {"text/css"} 
                ".js" {"text/javascript"} 
                default {"application/octet-stream"} 
            } 
    
            Set-AzureStorageBlobContent ` 
                -Container $StorageContainer ` 
                -Context $context ` 
                -File $file.FullName ` 
                -Blob $blobFileName ` 
                -Properties @{ContentType=$contentType} ` 
                -Force 
        } 
    

Referencing CDN assets

Another problem to solve is how to reference the files on the CDN, instead of the relative files. Different solutions are there, most of them using helper functions to inject to proper prefix to the relative path (Some answers to following question can help you: ASP.NET MVC Relative Paths).

I suggest having a centralized way of building CDN assets urls, you could even implement some kind cache killer (for this you need to enable query string parameters on Azure CDN):

Razor:

<img src="@Helper.ToCdnUrl("images/asset1.png")">

Helper method:

public static string ToCdnUrl(string relativePath)
{
    string prefix = ConfigurationManager.AppSettings["CdnUrlBasePath"];
    string sufix = ConfigurationManager.AppSettings["StaticFilesVersion"];
    return String.concat(prefix, relativePath, "?v=", sufix);
}

AppSettings:

<add key="CdnUrlBasePath" value="://<yourCDNName>.vo.msecnd.net/" />
<add key="StaticFilesVersion" value="1.01" />

Rendered HTML:

<img src="://<yourCDNName>.vo.msecnd.net/images/asset1.png?v=1.01">
Allmon answered 19/5, 2015 at 12:37 Comment(1)
once this page doesn't work anymore, your answer will become uselessMelancholy
Y
3

If CDN or Blob Storage are not options, a simple way to make a folder serve files in Azure (or standard IIS) is to create a Web.config file inside the folder, like this:

<configuration>
    <system.webServer>
        <handlers>
           <clear />
            <add 
                name="StaticFile" 
                path="*" verb="*" 
                modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" 
                resourceType="Either" 
                requireAccess="Read" />
        </handlers>
        <staticContent>
            <mimeMap fileExtension=".*" mimeType="application/octet-stream" />
        </staticContent>
    </system.webServer>
</configuration> 
Yean answered 25/6, 2016 at 7:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.