Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / IIS

Synchronize file date time on multiple IIS servers and fix ETag discrepency

0.00/5 (No votes)
17 May 2011CPOL 23.3K  
Files with different date time get different ETag generated by IIS. As a result, on a web server farm, each webserver sends different ETag for the same file as the files are copied to those servers at different date time. Here's a script that can set date time of same file across multiple servers to
When you deploy the same website on multiple webservers, you end up having each file getting different last modified date. As a result, each IIS produces different ETag for the static files. If user is hitting different servers for the same file (due to load balancing), each IIS is responding with different ETag and thus browser downloading the same file over and over again. if you have 3 servers, same user has most likely downloaded the same file thrice. This gives poor page load performance.
Moreover, if you want to mirror two or more locations using one location as a base, not only you need to copy the same files but you need to set the same Create Date and Last Modified Date on the files. Otherwise they aren’t true mirror. There are various use cases where you need a complete mirror not only at file content level but also at file date time level.
Here’s a powershell script that will do the job for you:
# Path of the base folder. File date times in this folder is used as the base.
$SourceFolder = ".\Folder1"
# Put all the other locations here. These locations must have the same folder structure as the base
$DestFolders = @('.\Folder2', '.\Folder3')    
function sync($sourcePath, $destinationPath)
{
    $sourceFiles = [System.IO.Directory]::GetFiles($sourcePath);
    foreach ($sourceFileName in $sourceFiles)
    {
        $sourceFile = Get-Item $sourceFileName
        $destFilePath = Join-Path -Path $destinationPath -ChildPath $sourceFile.Name
        $destFile = Get-Item $destFilePath
        if ($destFile.Length -eq $sourceFile.Length)
        {
            $destFile.LastWriteTime = $sourceFile.LastWriteTime;
            $destFile.CreationTime = $sourceFile.CreationTime;
            
            Write-Host ("SYNCED: " + $sourceFileName + " -> " + $destinationPath)
        }
        else
        {
            Write-Host ("SIZE DOES NOT MATCH: " + $sourceFileName + " -> " + $destinationPath)
        }
    }
    
    $childFolders = [System.IO.Directory]::GetDirectories($sourcePath);
    foreach ($childFolderName in $childFolders)
    {        
        $childFolder = Get-Item $childFolderName
        $destFolderPath = Join-Path -Path $destinationPath -ChildPath $childFolder.Name
        $destFolder = Get-Item $destFolderPath
        sync $childFolder.FullName $destFolder.FullName
    }
}
$Source = Get-Item $SourceFolder
foreach ($destFolderName in $DestFolders)
{
    $destFolder = Get-Item $destFolderName
    sync $Source.FullName $destFolder.FullName
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)